Repository: dtolnay/cxx (rust)

Issue:
`#[cxx_name = "type"]` yields an error "expected identifier"
I have a struct in C++ with a field named **type**:

```cpp
struct X {
    int32 type;
}
```

Then I represent it in Rust as a shared type inside of the `#[cxx::bridge]` mod:

```rust
struct X {
    #[cxx_name = "type"]
    x_type: i32,
}
```

But this yields an error:
```
 error[cxxbridge]: expected identifier
      ┌─ src/lib.rs:138:22
      │
  138 │         #[cxx_name = "type"]
      │                      ^^^^^^ expected identifier
```

At the same time other values for `cxx_name` such as `type1` work fine.

Pull request description:
Support cxx_name containing name that is Rust keyword
Fixes #1149.

Patch:
diff --git a/syntax/names.rs b/syntax/names.rs
index 8b93ac5c..329a1022 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -3,7 +3,8 @@ use crate::syntax::{Lifetimes, NamedType, Pair, Symbol};
 use proc_macro2::{Ident, Span};
 use std::fmt::{self, Display};
 use std::iter;
-use syn::parse::{Error, Result};
+use syn::ext::IdentExt;
+use syn::parse::{Error, Parser, Result};
 use syn::punctuated::Punctuated;
 
 #[derive(Clone)]
@@ -41,7 +42,7 @@ impl ForeignName {
     pub fn parse(text: &str, span: Span) -> Result<Self> {
         // TODO: support C++ names containing whitespace (`unsigned int`) or
         // non-alphanumeric characters (`operator++`).
-        match syn::parse_str::<Ident>(text) {
+        match Ident::parse_any.parse_str(text) {
             Ok(ident) => {
                 let text = ident.to_string();
                 Ok(ForeignName { text })


Test patch:
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index bad8128b..d6a5f028 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -43,6 +43,7 @@ pub mod ffi {
     #[namespace = "A"]
     #[derive(Copy, Clone, Default)]
     struct AShared {
+        #[cxx_name = "type"]
         z: usize,
     }
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 984e2220..8cf74beb 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -86,7 +86,9 @@ std::unique_ptr<::H::H> c_return_ns_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_ns_ref(const ::A::AShared &shared) {
+  return shared.type;
+}
 
 const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared) {
   return shared.z;
@@ -240,7 +242,7 @@ void c_take_shared(Shared shared) {
 }
 
 void c_take_ns_shared(::A::AShared shared) {
-  if (shared.z == 2020) {
+  if (shared.type == 2020) {
     cxx_test_suite_set_correct();
   }
 }
@@ -397,7 +399,7 @@ 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;
+    sum += i.type;
   }
   if (sum == 2021) {
     cxx_test_suite_set_correct();
@@ -916,7 +918,7 @@ void ns_c_take_trivial(::tests::D d) {
 }
 
 void ns_c_take_ns_shared(::A::AShared shared) {
-  if (shared.z == 2020) {
+  if (shared.type == 2020) {
     cxx_test_suite_set_correct();
   }
 }