Repository: dtolnay/cxx (language: rust)

Issue:
Accept unquoted path in type_id macro
Currently [cxx::type_id!](https://docs.rs/cxx/0.3.3/cxx/trait.ExternType.html#integrating-with-bindgen-generated-types) requires that you give it a string literal.

```rust
type Id = type_id!("folly::StringPiece");
```

Usually this is fine but it is inconvenient if the path needs to be constructed by a macro_rules macro. We should allow passing the argument as an unquoted path.

```rust
type Id = type_id!(folly::StringPiece);

// from in a macro:
type Id = type_id!(folly::$ident);
```


Discussion / hints:

Fix patch:
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index c2ad38b09..fae874a6c 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 445da2ba7..5c5d9ccc5 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 d6db7cb2e..03422d110 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;


Test patch: