Actually run destructors of C++ messages.

PiperOrigin-RevId: 525244271
pull/12498/head
Miguel Young de la Sota 2 years ago committed by Copybara-Service
parent 6ad1a6d674
commit 35b9813f85
  1. 7
      src/google/protobuf/compiler/rust/BUILD.bazel
  2. 24
      src/google/protobuf/compiler/rust/accessors/singular_bytes.cc
  3. 24
      src/google/protobuf/compiler/rust/accessors/singular_scalar.cc
  4. 100
      src/google/protobuf/compiler/rust/message.cc
  5. 26
      src/google/protobuf/compiler/rust/naming.cc
  6. 6
      src/google/protobuf/compiler/rust/naming.h

@ -36,11 +36,11 @@ cc_library(
copts = COPTS, copts = COPTS,
include_prefix = "google/protobuf/compiler/rust", include_prefix = "google/protobuf/compiler/rust",
deps = [ deps = [
":accessors",
":context", ":context",
":naming", ":naming",
"//src/google/protobuf:protobuf_nowkt", "//src/google/protobuf:protobuf_nowkt",
"//src/google/protobuf/compiler/cpp:names", "//src/google/protobuf/compiler/cpp:names",
":accessors",
"@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/log:absl_log", "@com_google_absl//absl/log:absl_log",
], ],
@ -57,16 +57,15 @@ cc_library(
copts = COPTS, copts = COPTS,
include_prefix = "google/protobuf/compiler/rust", include_prefix = "google/protobuf/compiler/rust",
deps = [ deps = [
"//src/google/protobuf:protobuf_nowkt",
"//src/google/protobuf/compiler/cpp:names_internal",
":context", ":context",
":naming", ":naming",
"//src/google/protobuf:protobuf_nowkt",
"//src/google/protobuf/compiler/cpp:names_internal",
"@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/strings", "@com_google_absl//absl/strings",
], ],
) )
cc_library( cc_library(
name = "context", name = "context",
srcs = ["context.cc"], srcs = ["context.cc"],

@ -50,10 +50,10 @@ class SingularBytes final : public AccessorGenerator {
field.Emit( field.Emit(
{ {
{"field", field.desc().name()}, {"field", field.desc().name()},
{"hazzer_thunk", GetAccessorThunkName(field, "has")}, {"hazzer_thunk", Thunk(field, "has")},
{"getter_thunk", GetAccessorThunkName(field, "")}, {"getter_thunk", Thunk(field, "get")},
{"setter_thunk", GetAccessorThunkName(field, "set")}, {"setter_thunk", Thunk(field, "set")},
{"clearer_thunk", GetAccessorThunkName(field, "clear")}, {"clearer_thunk", Thunk(field, "clear")},
}, },
R"rs( R"rs(
pub fn $field$(&self) -> Option<&[u8]> { pub fn $field$(&self) -> Option<&[u8]> {
@ -77,10 +77,10 @@ class SingularBytes final : public AccessorGenerator {
void InExternC(Context<FieldDescriptor> field) const override { void InExternC(Context<FieldDescriptor> field) const override {
field.Emit( field.Emit(
{ {
{"hazzer_thunk", GetAccessorThunkName(field, "has")}, {"hazzer_thunk", Thunk(field, "has")},
{"getter_thunk", GetAccessorThunkName(field, "")}, {"getter_thunk", Thunk(field, "get")},
{"setter_thunk", GetAccessorThunkName(field, "set")}, {"setter_thunk", Thunk(field, "set")},
{"clearer_thunk", GetAccessorThunkName(field, "clear")}, {"clearer_thunk", Thunk(field, "clear")},
}, },
R"rs( R"rs(
fn $hazzer_thunk$(raw_msg: $NonNull$<u8>) -> bool; fn $hazzer_thunk$(raw_msg: $NonNull$<u8>) -> bool;
@ -95,10 +95,10 @@ class SingularBytes final : public AccessorGenerator {
{ {
{"field", field.desc().name()}, {"field", field.desc().name()},
{"namespace", cpp::Namespace(field.desc().containing_type())}, {"namespace", cpp::Namespace(field.desc().containing_type())},
{"hazzer_thunk", GetAccessorThunkName(field, "has")}, {"hazzer_thunk", Thunk(field, "has")},
{"getter_thunk", GetAccessorThunkName(field, "")}, {"getter_thunk", Thunk(field, "get")},
{"setter_thunk", GetAccessorThunkName(field, "set")}, {"setter_thunk", Thunk(field, "set")},
{"clearer_thunk", GetAccessorThunkName(field, "clear")}, {"clearer_thunk", Thunk(field, "clear")},
}, },
R"cc( R"cc(
bool $hazzer_thunk$($namespace$::$Msg$* msg) { bool $hazzer_thunk$($namespace$::$Msg$* msg) {

@ -51,10 +51,10 @@ class SingularScalar final : public AccessorGenerator {
{ {
{"field", field.desc().name()}, {"field", field.desc().name()},
{"Scalar", PrimitiveRsTypeName(field)}, {"Scalar", PrimitiveRsTypeName(field)},
{"hazzer_thunk", GetAccessorThunkName(field, "has")}, {"hazzer_thunk", Thunk(field, "has")},
{"getter_thunk", GetAccessorThunkName(field, "")}, {"getter_thunk", Thunk(field, "get")},
{"setter_thunk", GetAccessorThunkName(field, "set")}, {"setter_thunk", Thunk(field, "set")},
{"clearer_thunk", GetAccessorThunkName(field, "clear")}, {"clearer_thunk", Thunk(field, "clear")},
}, },
R"rs( R"rs(
pub fn $field$(&self) -> Option<$Scalar$> { pub fn $field$(&self) -> Option<$Scalar$> {
@ -76,10 +76,10 @@ class SingularScalar final : public AccessorGenerator {
field.Emit( field.Emit(
{ {
{"Scalar", PrimitiveRsTypeName(field)}, {"Scalar", PrimitiveRsTypeName(field)},
{"hazzer_thunk", GetAccessorThunkName(field, "has")}, {"hazzer_thunk", Thunk(field, "has")},
{"getter_thunk", GetAccessorThunkName(field, "")}, {"getter_thunk", Thunk(field, "get")},
{"setter_thunk", GetAccessorThunkName(field, "set")}, {"setter_thunk", Thunk(field, "set")},
{"clearer_thunk", GetAccessorThunkName(field, "clear")}, {"clearer_thunk", Thunk(field, "clear")},
}, },
R"rs( R"rs(
fn $hazzer_thunk$(raw_msg: $NonNull$<u8>) -> bool; fn $hazzer_thunk$(raw_msg: $NonNull$<u8>) -> bool;
@ -95,10 +95,10 @@ class SingularScalar final : public AccessorGenerator {
{"field", field.desc().name()}, {"field", field.desc().name()},
{"Scalar", cpp::PrimitiveTypeName(field.desc().cpp_type())}, {"Scalar", cpp::PrimitiveTypeName(field.desc().cpp_type())},
{"namespace", cpp::Namespace(field.desc().containing_type())}, {"namespace", cpp::Namespace(field.desc().containing_type())},
{"hazzer_thunk", GetAccessorThunkName(field, "has")}, {"hazzer_thunk", Thunk(field, "has")},
{"getter_thunk", GetAccessorThunkName(field, "")}, {"getter_thunk", Thunk(field, "get")},
{"setter_thunk", GetAccessorThunkName(field, "set")}, {"setter_thunk", Thunk(field, "set")},
{"clearer_thunk", GetAccessorThunkName(field, "clear")}, {"clearer_thunk", Thunk(field, "clear")},
}, },
R"cc( R"cc(
bool $hazzer_thunk$($namespace$::$Msg$* msg) { bool $hazzer_thunk$($namespace$::$Msg$* msg) {

@ -65,15 +65,15 @@ void MessageStructFields(Context<Descriptor> msg) {
void MessageNew(Context<Descriptor> msg) { void MessageNew(Context<Descriptor> msg) {
switch (msg.opts().kernel) { switch (msg.opts().kernel) {
case Kernel::kCpp: case Kernel::kCpp:
msg.Emit(R"rs( msg.Emit({{"new_thunk", Thunk(msg, "new")}}, R"rs(
Self { msg: unsafe { __rust_proto_thunk__$pkg_Msg$__new() } } Self { msg: unsafe { $new_thunk$() } }
)rs"); )rs");
return; return;
case Kernel::kUpb: case Kernel::kUpb:
msg.Emit(R"rs( msg.Emit({{"new_thunk", Thunk(msg, "new")}}, R"rs(
let arena = unsafe { $pb$::Arena::new() }; let arena = unsafe { $pb$::Arena::new() };
let msg = unsafe { $pkg_Msg$_new(arena) }; let msg = unsafe { $new_thunk$(arena) };
$Msg$ { msg, arena } $Msg$ { msg, arena }
)rs"); )rs");
return; return;
@ -85,17 +85,17 @@ void MessageNew(Context<Descriptor> msg) {
void MessageSerialize(Context<Descriptor> msg) { void MessageSerialize(Context<Descriptor> msg) {
switch (msg.opts().kernel) { switch (msg.opts().kernel) {
case Kernel::kCpp: case Kernel::kCpp:
msg.Emit(R"rs( msg.Emit({{"serialize_thunk", Thunk(msg, "serialize")}}, R"rs(
unsafe { __rust_proto_thunk__$pkg_Msg$__serialize(self.msg) } unsafe { $serialize_thunk$(self.msg) }
)rs"); )rs");
return; return;
case Kernel::kUpb: case Kernel::kUpb:
msg.Emit(R"rs( msg.Emit({{"serialize_thunk", Thunk(msg, "serialize")}}, R"rs(
let arena = unsafe { $pb$::__runtime::upb_Arena_New() }; let arena = unsafe { $pb$::__runtime::upb_Arena_New() };
let mut len = 0; let mut len = 0;
unsafe { unsafe {
let data = $pkg_Msg$_serialize(self.msg, arena, &mut len); let data = $serialize_thunk$(self.msg, arena, &mut len);
$pb$::SerializedData::from_raw_parts(arena, data, len) $pb$::SerializedData::from_raw_parts(arena, data, len)
} }
)rs"); )rs");
@ -108,14 +108,18 @@ void MessageSerialize(Context<Descriptor> msg) {
void MessageDeserialize(Context<Descriptor> msg) { void MessageDeserialize(Context<Descriptor> msg) {
switch (msg.opts().kernel) { switch (msg.opts().kernel) {
case Kernel::kCpp: case Kernel::kCpp:
msg.Emit(R"rs( msg.Emit(
{
{"deserialize_thunk", Thunk(msg, "deserialize")},
},
R"rs(
let success = unsafe { let success = unsafe {
let data = $pb$::SerializedData::from_raw_parts( let data = $pb$::SerializedData::from_raw_parts(
$NonNull$::new(data.as_ptr() as *mut _).unwrap(), $NonNull$::new(data.as_ptr() as *mut _).unwrap(),
data.len(), data.len(),
); );
__rust_proto_thunk__$pkg_Msg$__deserialize(self.msg, data) $deserialize_thunk$(self.msg, data)
}; };
success.then_some(()).ok_or($pb$::ParseError) success.then_some(()).ok_or($pb$::ParseError)
)rs"); )rs");
@ -135,30 +139,52 @@ void MessageDeserialize(Context<Descriptor> msg) {
void MessageExterns(Context<Descriptor> msg) { void MessageExterns(Context<Descriptor> msg) {
switch (msg.opts().kernel) { switch (msg.opts().kernel) {
case Kernel::kCpp: case Kernel::kCpp:
msg.Emit(R"rs( msg.Emit(
fn __rust_proto_thunk__$pkg_Msg$__new() -> $NonNull$<u8>; {
fn __rust_proto_thunk__$pkg_Msg$__serialize(raw_msg: $NonNull$<u8>) {"new_thunk", Thunk(msg, "new")},
-> $pb$::SerializedData; {"delete_thunk", Thunk(msg, "delete")},
fn __rust_proto_thunk__$pkg_Msg$__deserialize( {"serialize_thunk", Thunk(msg, "serialize")},
raw_msg: $NonNull$<u8>, {"deserialize_thunk", Thunk(msg, "deserialize")},
data: $pb$::SerializedData, },
) -> bool; R"rs(
fn $new_thunk$() -> $NonNull$<u8>;
fn $delete_thunk$(raw_msg: $NonNull$<u8>);
fn $serialize_thunk$(raw_msg: $NonNull$<u8>) -> $pb$::SerializedData;
fn $deserialize_thunk$( raw_msg: $NonNull$<u8>, data: $pb$::SerializedData) -> bool;
)rs"); )rs");
return; return;
case Kernel::kUpb: case Kernel::kUpb:
msg.Emit(R"rs( msg.Emit(
fn $pkg_Msg$_new(arena: *mut $pb$::Arena) -> $NonNull$<u8>; {
fn $pkg_Msg$_serialize( {"new_thunk", Thunk(msg, "new")},
{"serialize_thunk", Thunk(msg, "serialize")},
},
R"rs(
fn $new_thunk$(arena: *mut $pb$::Arena) -> $NonNull$<u8>;
fn $serialize_thunk$(
msg: $NonNull$<u8>, msg: $NonNull$<u8>,
arena: *mut $pb$::Arena, arena: *mut $pb$::Arena,
len: &mut usize) -> $NonNull$<u8>; len: &mut usize,
) -> $NonNull$<u8>;
)rs"); )rs");
return; return;
} }
ABSL_LOG(FATAL) << "unreachable"; ABSL_LOG(FATAL) << "unreachable";
} }
void MessageDrop(Context<Descriptor> msg) {
if (msg.is_upb()) {
// Nothing to do here; drop glue (which will run drop(self.arena)
// automatically) is sufficient.
return;
}
msg.Emit({{"delete_thunk", Thunk(msg, "delete")}}, R"rs(
unsafe { $delete_thunk$(self.msg); }
)rs");
}
} // namespace } // namespace
MessageGenerator::MessageGenerator(Context<Descriptor> msg) { MessageGenerator::MessageGenerator(Context<Descriptor> msg) {
@ -176,11 +202,11 @@ void MessageGenerator::GenerateRs(Context<Descriptor> msg) {
msg.Emit( msg.Emit(
{ {
{"Msg", msg.desc().name()}, {"Msg", msg.desc().name()},
{"pkg_Msg", GetUnderscoreDelimitedFullName(msg)},
{"Msg.fields", [&] { MessageStructFields(msg); }}, {"Msg.fields", [&] { MessageStructFields(msg); }},
{"Msg::new", [&] { MessageNew(msg); }}, {"Msg::new", [&] { MessageNew(msg); }},
{"Msg::serialize", [&] { MessageSerialize(msg); }}, {"Msg::serialize", [&] { MessageSerialize(msg); }},
{"Msg::deserialize", [&] { MessageDeserialize(msg); }}, {"Msg::deserialize", [&] { MessageDeserialize(msg); }},
{"Msg::drop", [&] { MessageDrop(msg); }},
{"Msg_externs", [&] { MessageExterns(msg); }}, {"Msg_externs", [&] { MessageExterns(msg); }},
{"accessor_fns", {"accessor_fns",
[&] { [&] {
@ -235,6 +261,14 @@ void MessageGenerator::GenerateRs(Context<Descriptor> msg) {
$accessor_fns$ $accessor_fns$
} // impl $Msg$ } // impl $Msg$
//~ We implement drop unconditionally, so that `$Msg$: Drop` regardless
//~ of kernel.
impl $std$::ops::Drop for $Msg$ {
fn drop(&mut self) {
$Msg::drop$
}
}
extern "C" { extern "C" {
$Msg_externs$ $Msg_externs$
@ -262,8 +296,11 @@ void MessageGenerator::GenerateThunkCc(Context<Descriptor> msg) {
{ {
{"abi", "\"C\""}, // Workaround for syntax highlight bug in VSCode. {"abi", "\"C\""}, // Workaround for syntax highlight bug in VSCode.
{"Msg", msg.desc().name()}, {"Msg", msg.desc().name()},
{"pkg_Msg", GetUnderscoreDelimitedFullName(msg)}, {"pkg", cpp::Namespace(&msg.desc())},
{"namespace", cpp::Namespace(&msg.desc())}, {"new_thunk", Thunk(msg, "new")},
{"delete_thunk", Thunk(msg, "delete")},
{"serialize_thunk", Thunk(msg, "serialize")},
{"deserialize_thunk", Thunk(msg, "deserialize")},
{"accessor_thunks", {"accessor_thunks",
[&] { [&] {
for (int i = 0; i < msg.desc().field_count(); ++i) { for (int i = 0; i < msg.desc().field_count(); ++i) {
@ -276,17 +313,12 @@ void MessageGenerator::GenerateThunkCc(Context<Descriptor> msg) {
}, },
R"cc( R"cc(
extern $abi$ { extern $abi$ {
void* __rust_proto_thunk__$pkg_Msg$__new() { void* $new_thunk$() { return new $pkg$::$Msg$(); }
return new $namespace$::$Msg$(); void $delete_thunk$(void* ptr) { delete static_cast<$pkg$::$Msg$*>(ptr); }
} google::protobuf::rust_internal::SerializedData $serialize_thunk$($pkg$::$Msg$ * msg) {
google::protobuf::rust_internal::SerializedData
__rust_proto_thunk__$pkg_Msg$__serialize($namespace$::$Msg$ * msg) {
return google::protobuf::rust_internal::SerializeMsg(msg); return google::protobuf::rust_internal::SerializeMsg(msg);
} }
bool $deserialize_thunk$($pkg$::$Msg$ * msg,
bool __rust_proto_thunk__$pkg_Msg$__deserialize(
$namespace$::$Msg$ * msg,
google::protobuf::rust_internal::SerializedData data) { google::protobuf::rust_internal::SerializedData data) {
return msg->ParseFromArray(data.data, data.len); return msg->ParseFromArray(data.data, data.len);
} }

@ -45,6 +45,14 @@ namespace google {
namespace protobuf { namespace protobuf {
namespace compiler { namespace compiler {
namespace rust { namespace rust {
namespace {
std::string GetUnderscoreDelimitedFullName(Context<Descriptor> msg) {
std::string result = msg.desc().full_name();
absl::StrReplaceAll({{".", "_"}}, &result);
return result;
}
} // namespace
std::string GetCrateName(Context<FileDescriptor> dep) { std::string GetCrateName(Context<FileDescriptor> dep) {
absl::string_view path = dep.desc().name(); absl::string_view path = dep.desc().name();
auto basename = path.substr(path.rfind('/') + 1); auto basename = path.substr(path.rfind('/') + 1);
@ -74,20 +82,17 @@ std::string GetHeaderFile(Context<FileDescriptor> file) {
return absl::StrCat(basename, ".proto.h"); return absl::StrCat(basename, ".proto.h");
} }
std::string GetUnderscoreDelimitedFullName(Context<Descriptor> msg) { std::string Thunk(Context<FieldDescriptor> field, absl::string_view op) {
std::string result = msg.desc().full_name(); // NOTE: When field.is_upb(), this functions outputs must match the symbols
absl::StrReplaceAll({{".", "_"}}, &result); // that the upbc plugin generates exactly. Failure to do so correctly results
return result; // in a link-time failure.
}
std::string GetAccessorThunkName(Context<FieldDescriptor> field,
absl::string_view op) {
absl::string_view prefix = field.is_cpp() ? "__rust_proto_thunk__" : ""; absl::string_view prefix = field.is_cpp() ? "__rust_proto_thunk__" : "";
std::string thunk = std::string thunk =
absl::StrCat(prefix, GetUnderscoreDelimitedFullName( absl::StrCat(prefix, GetUnderscoreDelimitedFullName(
field.WithDesc(field.desc().containing_type()))); field.WithDesc(field.desc().containing_type())));
if (field.is_upb() && op.empty()) { if (field.is_upb() && op == "get") {
absl::SubstituteAndAppend(&thunk, "_$0", field.desc().name()); absl::SubstituteAndAppend(&thunk, "_$0", field.desc().name());
} else { } else {
absl::SubstituteAndAppend(&thunk, "_$0_$1", op, field.desc().name()); absl::SubstituteAndAppend(&thunk, "_$0_$1", op, field.desc().name());
@ -96,6 +101,11 @@ std::string GetAccessorThunkName(Context<FieldDescriptor> field,
return thunk; return thunk;
} }
std::string Thunk(Context<Descriptor> msg, absl::string_view op) {
absl::string_view prefix = msg.is_cpp() ? "__rust_proto_thunk__" : "";
return absl::StrCat(prefix, GetUnderscoreDelimitedFullName(msg), "_", op);
}
absl::string_view PrimitiveRsTypeName(Context<FieldDescriptor> field) { absl::string_view PrimitiveRsTypeName(Context<FieldDescriptor> field) {
switch (field.desc().type()) { switch (field.desc().type()) {
case FieldDescriptor::TYPE_BOOL: case FieldDescriptor::TYPE_BOOL:

@ -48,10 +48,8 @@ std::string GetRsFile(Context<FileDescriptor> file);
std::string GetThunkCcFile(Context<FileDescriptor> file); std::string GetThunkCcFile(Context<FileDescriptor> file);
std::string GetHeaderFile(Context<FileDescriptor> file); std::string GetHeaderFile(Context<FileDescriptor> file);
std::string GetUnderscoreDelimitedFullName(Context<Descriptor> msg); std::string Thunk(Context<FieldDescriptor> field, absl::string_view op);
std::string Thunk(Context<Descriptor> msg, absl::string_view op);
std::string GetAccessorThunkName(Context<FieldDescriptor> field,
absl::string_view op);
bool IsSupportedFieldType(Context<FieldDescriptor> field); bool IsSupportedFieldType(Context<FieldDescriptor> field);

Loading…
Cancel
Save