Support for wchar_t
Hey,
I'd like to implement support for wchar_t as a primitive type (that will codegen into libc::wchar_t in the Rust leg and the built-in type in C++). I think I can write the code for it, but do you think this is a good idea? Relying on libc::wchar_t might introduce a dependency on the libc crate for autogenerated code; maybe we should define this type in this crate directly?
I think this is a bit similar to the desire to support c_int (https://github.com/dtolnay/cxx/pull/874) or &CStr (https://github.com/dtolnay/cxx/issues/681) - both are kind of blocked by https://github.com/dtolnay/cxx/issues/682.
I am not aware what is the current status of https://github.com/dtolnay/cxx/issues/682. I know that there was some activity in https://github.com/dtolnay/cxx/pull/908 - maybe it can be picked up, refreshed, augmented with tests (which IIUC are the only missing item from the checklist at the top of https://github.com/dtolnay/cxx/pull/908), and then considered for merging?
@anforowicz first of all, thanks for commenting and linking to these PRs - that really does seem relevant to what I want to do and would make it very easy for me to implement this feature if we decided to go for it. I think that this specific case actually doesn't stumble on the issue that blocks the other basic types. This is because, the types c_int and CStr have a name that someone might want to use for an opaque type; however, wchar_t is a reserved keyword in C++ and therefore has definitely never been used as the name to an opaque type, so we can safely use it in the Rust side without worrying about conflicting with a user-defined type.
wchar_tis a reserved keyword in C++ and therefore has definitely never been used as the name to an opaque type, so we can safely use it
Good point.
I've tried tweaking tests/ffi/lib.rs and checked that indeed cargo test --workspace already fails today (with kind of icky, impl-detail-related errors) in the following scenarios:
- Using
extern "C++" { type wchar_t; }:lib.rs.cc:1229:9: error: expected nested-name-specifier before 'wchar_t': using wchar_t = ::tests::wchar_ - Using
extern "Rust" { type wchar_t; }:lib.rs.cc:1239:10: error: expected identifier before 'wchar_t': struct wchar_t - Declaring a shared
struct wchar_t { x: u32 }(same first error as above)
I wonder if the first step we can take here may be to do the following:
- Tweak
syntax/check.rsto detect the reserved type name earlier + fail earlier with a nicer error message (earlier = in proc-macro / in cxxbridge, rather than when compiling the generated C++ code).- Maybe
fn checked_reserved_namecan just be tweaked to coverwchar_t? - I guess we should also consider covering
char8_t,char16_t, andchar32_t. And maybe alsolong,short,float,double,signed, andunsigned. And maybevoid? - Not sure about other, non-type-related reserved C++ keywords (e.g.
namespaceorprivate, etc).- Not sure if a single
fn checked_reserved_nameis okay. Or if we need separatefn checked_reserved_type_nameandfn checked_reserved_fn_name(would a reserved C++ keyword ever be okay in one context [say as a type name] but not okay in another context?). - Maybe this can be a separate follow-up to keep things small/simple/incremental?
- Not sure if a single
- Maybe
- Add end-to-end testcases for error message under
tests/ui
Just a side-note / I don't have a strong or well-formed opinion: I guess that initially mapping wchar_t to libc::wchar_t SGTM. At the same time, I wanted to point out https://docs.rs/ffi_11 - see it's README.md for a rationale for having a different crate / C++=>Rust-type-mapping-approach. If we want to switch to ffi_11 in the future, then it would be a breaking change I think, which seems a bit unfortunate :-/.