Fix how mutability of the pointee is represented in the generated code.
Before this CL, `*mut *const f32` and `*const *mut f32` would *both*
translate into `const float**`.
After this CL we have:
* `*mut *const f32` => `float const **`
* `*const *mut f32` => `float *const *`
PiperOrigin-RevId: 540624376
diff --git a/cc_bindings_from_rs/bindings.rs b/cc_bindings_from_rs/bindings.rs
index 3936e8c..a61294a 100644
--- a/cc_bindings_from_rs/bindings.rs
+++ b/cc_bindings_from_rs/bindings.rs
@@ -512,7 +512,7 @@
format!("Failed to format the pointee of the pointer type `{ty}`")
})?;
prereqs.move_defs_to_fwd_decls();
- CcSnippet { prereqs, tokens: quote! { #const_qualifier #tokens * } }
+ CcSnippet { prereqs, tokens: quote! { #tokens #const_qualifier * } }
}
ty::TyKind::FnPtr(sig) => {
@@ -2250,11 +2250,11 @@
// below also matters.
struct S;
...
- inline void f(const ::rust_out::S* __param_0);
+ inline void f(::rust_out::S const* __param_0);
...
struct CRUBIT_INTERNAL_RUST_TYPE(...) alignas(...) S final { ... }
...
- inline void f(const ::rust_out::S* __param_0) { ... }
+ inline void f(::rust_out::S const* __param_0) { ... }
...
} // namespace rust_out
}
@@ -2404,7 +2404,7 @@
test_generated_bindings(test_src, |bindings| {
let bindings = bindings.unwrap();
assert_cc_not_matches!(bindings.h_body, quote! { struct S; });
- assert_cc_matches!(bindings.h_body, quote! { void f(const ::rust_out::S* _s); });
+ assert_cc_matches!(bindings.h_body, quote! { void f(::rust_out::S const* _s); });
});
}
@@ -2432,7 +2432,7 @@
bindings.h_body,
quote! {
static inline ::rust_out::S create(); ...
- const ::rust_out::S* field; ...
+ ::rust_out::S const* field; ...
}
);
});
@@ -5138,17 +5138,15 @@
("SomeStruct", ("::rust_out::SomeStruct", "", "SomeStruct", "")),
("SomeEnum", ("::rust_out::SomeEnum", "", "SomeEnum", "")),
("SomeUnion", ("::rust_out::SomeUnion", "", "SomeUnion", "")),
- ("*const i32", ("const std::int32_t*", "<cstdint>", "", "")),
+ ("*const i32", ("std :: int32_t const *", "<cstdint>", "", "")),
("*mut i32", ("std::int32_t*", "<cstdint>", "", "")),
// `SomeStruct` is a `fwd_decls` prerequisite (not `defs` prerequisite):
("*mut SomeStruct", ("::rust_out::SomeStruct*", "", "", "SomeStruct")),
// Testing propagation of deeper/nested `fwd_decls`:
("*mut *mut SomeStruct", (":: rust_out :: SomeStruct * *", "", "", "SomeStruct")),
// Testing propagation of `const` / `mut` qualifiers:
- // TODO(b/286876315): The 2 distinct inputs below should *not* result in the same
- // output.
- ("*mut *const f32", ("const float * *", "", "", "")),
- ("*const *mut f32", ("const float * *", "", "", "")),
+ ("*mut *const f32", ("float const * *", "", "", "")),
+ ("*const *mut f32", ("float * const *", "", "", "")),
(
// Rust function pointers are non-nullable, so when function pointers are used as a
// parameter type (i.e. in `TypeLocation::FnParam`) then we can translate to
@@ -5167,7 +5165,7 @@
// function *reference*.
"*const extern \"C\" fn (f32, f32) -> f32",
(
- "const crubit :: type_identity_t < float (float , float) > * *",
+ "crubit :: type_identity_t < float (float , float) > * const *",
"\"crubit/support/for/tests/internal/cxx20_backports.h\"",
"",
"",
diff --git a/cc_bindings_from_rs/test/structs/structs.rs b/cc_bindings_from_rs/test/structs/structs.rs
index eaef905..c373d4d 100644
--- a/cc_bindings_from_rs/test/structs/structs.rs
+++ b/cc_bindings_from_rs/test/structs/structs.rs
@@ -244,3 +244,18 @@
_dynamically_sized_field: [i32],
}
}
+
+/// This is a regression test for b/286876315 - it verifies that the mutability
+/// qualifiers of nested pointers are correctly propagated.
+pub mod nested_ptr_type_mutability_qualifiers {
+ pub struct SomeStruct {
+ pub mut_const_ptr: *mut *const f32,
+ pub const_mut_ptr: *const *mut f32,
+ }
+
+ impl Default for SomeStruct {
+ fn default() -> Self {
+ Self { mut_const_ptr: std::ptr::null_mut(), const_mut_ptr: std::ptr::null() }
+ }
+ }
+}
diff --git a/cc_bindings_from_rs/test/structs/structs_test.cc b/cc_bindings_from_rs/test/structs/structs_test.cc
index d22427b..46d9fec 100644
--- a/cc_bindings_from_rs/test/structs/structs_test.cc
+++ b/cc_bindings_from_rs/test/structs/structs_test.cc
@@ -2,6 +2,7 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#include <type_traits>
#include <utility>
#include "gmock/gmock.h"
@@ -76,5 +77,18 @@
EXPECT_EQ(111.0 * 222.0, test::thunkless_inspect(std::move(product)));
}
+// This is a regression test for b/286876315 - it verifies that the mutability
+// qualifiers of nested pointers / pointees are correctly propagated.
+TEST(StructsTest, NestedPtrTypeMutabilityQualifiers) {
+ namespace test = structs::nested_ptr_type_mutability_qualifiers;
+ test::SomeStruct s;
+ ASSERT_EQ(nullptr, s.mut_const_ptr);
+ ASSERT_EQ(nullptr, s.const_mut_ptr);
+
+ // Verify that the `const` qualifiers got propagated correctly.
+ static_assert(std::is_same_v<decltype(s.mut_const_ptr), float const**>);
+ static_assert(std::is_same_v<decltype(s.const_mut_ptr), float* const*>);
+}
+
} // namespace
} // namespace crubit