Cover `enclosing_namespace_id` in `IncompleteRecord::ToJson`.
PiperOrigin-RevId: 474810361
diff --git a/rs_bindings_from_cc/ir.cc b/rs_bindings_from_cc/ir.cc
index 90641f5..3083d12 100644
--- a/rs_bindings_from_cc/ir.cc
+++ b/rs_bindings_from_cc/ir.cc
@@ -382,6 +382,7 @@
{"id", id},
{"owning_target", owning_target},
{"record_type", RecordTypeToString(record_type)},
+ {"enclosing_namespace_id", enclosing_namespace_id},
};
return llvm::json::Object{
diff --git a/rs_bindings_from_cc/ir_from_cc_test.rs b/rs_bindings_from_cc/ir_from_cc_test.rs
index 96775ec..b05e88e 100644
--- a/rs_bindings_from_cc/ir_from_cc_test.rs
+++ b/rs_bindings_from_cc/ir_from_cc_test.rs
@@ -2371,6 +2371,46 @@
}
#[test]
+fn test_struct_forward_declaration_in_namespace() -> Result<()> {
+ let ir = ir_from_cc(
+ r#"
+ namespace MyNamespace {
+ struct FwdDeclared;
+ }
+ "#,
+ )?;
+
+ assert_eq!(1, ir.namespaces().count());
+ let ns = ir.namespaces().next().unwrap();
+ assert_eq!("MyNamespace", ns.name.identifier);
+ assert_eq!(1, ns.child_item_ids.len());
+
+ let ns_id = ns.id;
+ let child_id = ns.child_item_ids[0];
+ assert_ir_matches!(
+ ir,
+ quote! {
+ Namespace(Namespace {
+ name: "MyNamespace" ...
+ id: ItemId(#ns_id) ...
+ child_item_ids: [ItemId(#child_id)] ...
+ enclosing_record_id: None ...
+ enclosing_namespace_id: None ...
+ }),
+ IncompleteRecord(IncompleteRecord {
+ cc_name: "FwdDeclared" ...
+ rs_name: "FwdDeclared" ...
+ id: ItemId(#child_id) ...
+ ...
+ enclosing_namespace_id: Some(ItemId(#ns_id)) ...
+ }),
+ }
+ );
+
+ Ok(())
+}
+
+#[test]
fn test_union() {
let ir = ir_from_cc("union SomeUnion { int first_field; int second_field; };").unwrap();
assert_ir_matches!(
diff --git a/rs_bindings_from_cc/test/struct/forward_declarations/BUILD b/rs_bindings_from_cc/test/struct/forward_declarations/BUILD
index 10baa72..cf3527e 100644
--- a/rs_bindings_from_cc/test/struct/forward_declarations/BUILD
+++ b/rs_bindings_from_cc/test/struct/forward_declarations/BUILD
@@ -26,6 +26,11 @@
],
)
+cc_library(
+ name = "no_definition_in_headers",
+ hdrs = ["no_definition_in_headers.h"],
+)
+
rust_test(
name = "forward_declarations_test",
srcs = ["forward_declarations_test.rs"],
@@ -33,6 +38,7 @@
":declaration_1",
":declaration_2",
":definition",
+ ":no_definition_in_headers",
],
deps = [
"//rs_bindings_from_cc/support:ctor",
diff --git a/rs_bindings_from_cc/test/struct/forward_declarations/forward_declarations_test.rs b/rs_bindings_from_cc/test/struct/forward_declarations/forward_declarations_test.rs
index 5187393..adef747 100644
--- a/rs_bindings_from_cc/test/struct/forward_declarations/forward_declarations_test.rs
+++ b/rs_bindings_from_cc/test/struct/forward_declarations/forward_declarations_test.rs
@@ -190,3 +190,11 @@
let nonunpin_ref = &*nonunpin;
assert_eq!(123, declaration_1::InlineFunctionTakingNonunpinStruct(nonunpin_ref.cc_cast()));
}
+
+#[test]
+fn test_forward_declared_used_as_field_type() {
+ // This is a regression test for b/246962427. This mostly verifies that the
+ // generated bindings compile (and are usable at a very basic level).
+ use no_definition_in_headers::no_definition_in_headers::*;
+ let _s = Defined { field: std::ptr::null_mut() };
+}
diff --git a/rs_bindings_from_cc/test/struct/forward_declarations/no_definition_in_headers.h b/rs_bindings_from_cc/test/struct/forward_declarations/no_definition_in_headers.h
new file mode 100644
index 0000000..dfc4a7d
--- /dev/null
+++ b/rs_bindings_from_cc/test/struct/forward_declarations/no_definition_in_headers.h
@@ -0,0 +1,28 @@
+// Part of the Crubit project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#ifndef THIRD_PARTY_CRUBIT_RS_BINDINGS_FROM_CC_TEST_STRUCT_FORWARD_DECLARATIONS_NO_DEFINITION_IN_HEADERS_H_
+#define THIRD_PARTY_CRUBIT_RS_BINDINGS_FROM_CC_TEST_STRUCT_FORWARD_DECLARATIONS_NO_DEFINITION_IN_HEADERS_H_
+
+#pragma clang lifetime_elision
+
+// This is a regression test for b/246962427.
+//
+// This test mimics `absl::SynchLocksHeld` which is forward-declared in
+// `absl/base/internal/thread_identity.h` and doesn't have a definition in any
+// headers (only in `absl/synchronization/mutex.cc`).
+//
+// OTOH, note that the no-definition-in-headers wasn't the root cause of
+// b/246962427. Instead, there was a minor problem in the integration between
+// A) `namespace` support and B) forward-declarations support.
+namespace no_definition_in_headers {
+
+struct FwdDeclared;
+
+struct Defined final {
+ FwdDeclared* field;
+};
+
+} // namespace no_definition_in_headers
+
+#endif // THIRD_PARTY_CRUBIT_RS_BINDINGS_FROM_CC_TEST_STRUCT_FORWARD_DECLARATIONS_NO_DEFINITION_IN_HEADERS_H_