Explicit names for anonymous parameters: `fn foo(_: f64, _: f64)`.
In theory, the names could be omitted in *some* C++ translations (e.g.
`void foo(double, double)`), but they are required in other scenarios:
1. Forwarding an argument to a Rust function with a different name
(e.g. `#[export_name = ...]` attribute and/or Rust-ABI functions).
`return ::__crubit_internal::export_name(need_param_name_here)`.
2. Irrefutable, destructuring pattern matching - e.g.:
`fn foo((x, y): (i32, i32)) {}`
(this CL doesn't yet provide test coverage for this scenario,
because types that support destructuring are not yet supported).
PiperOrigin-RevId: 486708734
diff --git a/cc_bindings_from_rs/bindings.rs b/cc_bindings_from_rs/bindings.rs
index 5f8fb68..73d623f 100644
--- a/cc_bindings_from_rs/bindings.rs
+++ b/cc_bindings_from_rs/bindings.rs
@@ -1101,6 +1101,33 @@
}
#[test]
+ fn test_format_def_fn_export_name_with_anonymous_parameter_names() {
+ let test_src = r#"
+ #[export_name = "export_name"]
+ pub extern "C" fn public_function(_: f64, _: f64) {}
+ "#;
+ test_format_def(test_src, "public_function", |result| {
+ let result = result.expect("Test expects success here");
+ assert!(result.includes.is_empty());
+ assert_cc_matches!(
+ result.api,
+ quote! {
+ inline void public_function(double __param_0, double __param_1) {
+ return ::__crubit_internal::export_name(__param_0, __param_1);
+ }
+ }
+ );
+ assert_cc_matches!(
+ result.internals.expect("This test expects separate extern-C decl"),
+ quote! {
+ extern "C" void export_name(double __param_0, double __param_1);
+ }
+ );
+ });
+ }
+
+
+ #[test]
fn test_format_def_unsupported_fn_param_type() {
let test_src = r#"
#[no_mangle]
diff --git a/common/code_gen_utils.rs b/common/code_gen_utils.rs
index 53d618a..e441062 100644
--- a/common/code_gen_utils.rs
+++ b/common/code_gen_utils.rs
@@ -17,6 +17,8 @@
/// Formats a C++ identifier. Panics when `ident` is a C++ reserved keyword.
pub fn format_cc_ident(ident: &str) -> Result<TokenStream> {
+ ensure!(!ident.is_empty(), "Empty string is not a valid C++ identifier");
+
// C++ doesn't have an equivalent of
// https://doc.rust-lang.org/rust-by-example/compatibility/raw_identifiers.html and therefore
// an error is returned when `ident` is a C++ reserved keyword.
@@ -279,6 +281,13 @@
}
#[test]
+ fn test_format_cc_ident_empty() {
+ let err = format_cc_ident("").expect_err("This test expects an error");
+ let msg = err.to_string();
+ assert_eq!(msg, "Empty string is not a valid C++ identifier");
+ }
+
+ #[test]
fn test_format_cc_ident_qualified_identifiers() {
// https://en.cppreference.com/w/cpp/language/identifiers#Qualified_identifiers