diff --git a/rust/codegen_traits.rs b/rust/codegen_traits.rs index d9a39411f..d23b9ecf6 100644 --- a/rust/codegen_traits.rs +++ b/rust/codegen_traits.rs @@ -14,7 +14,7 @@ use create::Parse; use interop::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop}; use read::Serialize; use std::fmt::Debug; -use write::{Clear, ClearAndParse}; +use write::{Clear, ClearAndParse, MergeFrom}; /// A trait that all generated owned message types implement. pub trait Message: SealedInternal @@ -24,7 +24,7 @@ pub trait Message: SealedInternal // Read traits: + Debug + Serialize // Write traits: - + Clear + ClearAndParse + + Clear + ClearAndParse + MergeFrom // Thread safety: + Send + Sync // Copy/Clone: @@ -57,7 +57,7 @@ pub trait MessageMut<'msg>: SealedInternal + Debug + Serialize // Write traits: // TODO: MsgMut should impl ClearAndParse. - + Clear + + Clear + MergeFrom // Thread safety: + Sync // Copy/Clone: @@ -94,6 +94,7 @@ pub(crate) mod read { /// traits. pub(crate) mod write { use super::SealedInternal; + use crate::AsView; pub trait Clear: SealedInternal { fn clear(&mut self); @@ -102,6 +103,10 @@ pub(crate) mod write { pub trait ClearAndParse: SealedInternal { fn clear_and_parse(&mut self, data: &[u8]) -> Result<(), crate::ParseError>; } + + pub trait MergeFrom: AsView + SealedInternal { + fn merge_from(&mut self, src: impl AsView); + } } /// Traits related to interop with C or C++. diff --git a/rust/prelude.rs b/rust/prelude.rs index d32f2ae29..e06a73d25 100644 --- a/rust/prelude.rs +++ b/rust/prelude.rs @@ -11,6 +11,6 @@ //! or less common items should be imported normally. pub use crate::{ - proto, AsMut, AsView, Clear, ClearAndParse, IntoMut, IntoView, Message, MessageMut, + proto, AsMut, AsView, Clear, ClearAndParse, IntoMut, IntoView, MergeFrom, Message, MessageMut, MessageView, Parse, Serialize, }; diff --git a/rust/proto_macro.rs b/rust/proto_macro.rs index b3f937d60..19e1063da 100644 --- a/rust/proto_macro.rs +++ b/rust/proto_macro.rs @@ -50,7 +50,7 @@ macro_rules! proto_internal { }; (@merge $msg:ident ..$expr:expr) => { - $msg.merge_from($expr); + $crate::MergeFrom::merge_from(&mut $msg, $expr); }; // @msg rules are used to set the fields of the message. There is a lot of duplication here diff --git a/rust/shared.rs b/rust/shared.rs index 59e7bd820..8e42de965 100644 --- a/rust/shared.rs +++ b/rust/shared.rs @@ -26,7 +26,7 @@ pub mod __public { create::Parse, interop::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop}, read::Serialize, - write::{Clear, ClearAndParse}, + write::{Clear, ClearAndParse, MergeFrom}, Message, MessageMut, MessageView, }; pub use crate::cord::{ProtoBytesCow, ProtoStringCow}; diff --git a/rust/test/shared/merge_from_test.rs b/rust/test/shared/merge_from_test.rs index 26eb3998e..feb9e1ad4 100644 --- a/rust/test/shared/merge_from_test.rs +++ b/rust/test/shared/merge_from_test.rs @@ -1,5 +1,5 @@ use googletest::prelude::*; -use protobuf::proto; +use protobuf::prelude::*; use unittest_rust_proto::{NestedTestAllTypes, TestAllTypes}; #[googletest::test] diff --git a/src/google/protobuf/compiler/rust/message.cc b/src/google/protobuf/compiler/rust/message.cc index ffbcfbf5b..4217bbee4 100644 --- a/src/google/protobuf/compiler/rust/message.cc +++ b/src/google/protobuf/compiler/rust/message.cc @@ -334,7 +334,7 @@ void UpbGeneratedMessageTraitImpls(Context& ctx, const Descriptor& msg) { } } -void MessageMergeFrom(Context& ctx, const Descriptor& msg) { +void MessageMutMergeFrom(Context& ctx, const Descriptor& msg) { switch (ctx.opts().kernel) { case Kernel::kCpp: ctx.Emit( @@ -342,10 +342,12 @@ void MessageMergeFrom(Context& ctx, const Descriptor& msg) { {"merge_from_thunk", ThunkName(ctx, msg, "merge_from")}, }, R"rs( - pub fn merge_from(&mut self, src: impl $pb$::AsView) { - // SAFETY: self and src are both valid `$Msg$`s. - unsafe { - $merge_from_thunk$(self.raw_msg(), src.as_view().raw_msg()); + impl $pb$::MergeFrom for $Msg$Mut<'_> { + fn merge_from(&mut self, src: impl $pb$::AsView) { + // SAFETY: self and src are both valid `$Msg$`s. + unsafe { + $merge_from_thunk$(self.raw_msg(), src.as_view().raw_msg()); + } } } )rs"); @@ -353,17 +355,19 @@ void MessageMergeFrom(Context& ctx, const Descriptor& msg) { case Kernel::kUpb: ctx.Emit( R"rs( - pub fn merge_from(&mut self, src: impl $pb$::AsView) { - // SAFETY: self and src are both valid `$Msg$`s. - unsafe { - assert!( - $pbr$::upb_Message_MergeFrom(self.raw_msg(), - src.as_view().raw_msg(), - ::MINI_TABLE, - // Use a nullptr for the ExtensionRegistry. - $std$::ptr::null(), - self.arena().raw()) - ); + impl $pb$::MergeFrom for $Msg$Mut<'_> { + fn merge_from(&mut self, src: impl $pb$::AsView) { + // SAFETY: self and src are both valid `$Msg$`s. + unsafe { + assert!( + $pbr$::upb_Message_MergeFrom(self.raw_msg(), + src.as_view().raw_msg(), + ::MINI_TABLE, + // Use a nullptr for the ExtensionRegistry. + $std$::ptr::null(), + self.arena().raw()) + ); + } } } )rs"); @@ -853,6 +857,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { {"Msg::clear_and_parse", [&] { MessageClearAndParse(ctx, msg); }}, {"Msg::drop", [&] { MessageDrop(ctx, msg); }}, {"Msg::debug", [&] { MessageDebug(ctx, msg); }}, + {"MsgMut::merge_from", [&] { MessageMutMergeFrom(ctx, msg); }}, {"Msg_externs", [&] { MessageExterns(ctx, msg); }}, {"accessor_fns", [&] { @@ -955,7 +960,6 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { {"into_proxied_impl", [&] { IntoProxiedForMessage(ctx, msg); }}, {"upb_generated_message_trait_impls", [&] { UpbGeneratedMessageTraitImpls(ctx, msg); }}, - {"msg_merge_from", [&] { MessageMergeFrom(ctx, msg); }}, {"repeated_impl", [&] { MessageProxiedInRepeated(ctx, msg); }}, {"map_value_impl", [&] { MessageProxiedInMapValue(ctx, msg); }}, {"unwrap_upb", @@ -998,6 +1002,13 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { } } + impl $pb$::MergeFrom for $Msg$ { + fn merge_from<'src>(&mut self, src: impl $pb$::AsView) { + let mut m = self.as_mut(); + $pb$::MergeFrom::merge_from(&mut m, src) + } + } + impl $pb$::Serialize for $Msg$ { fn serialize(&self) -> Result, $pb$::SerializeError> { $pb$::AsView::as_view(self).serialize() @@ -1141,6 +1152,8 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { } } + $MsgMut::merge_from$ + #[allow(dead_code)] impl<'msg> $Msg$Mut<'msg> { #[doc(hidden)] @@ -1173,8 +1186,6 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { $pb$::AsView::as_view(self).to_owned() } - $msg_merge_from$ - $raw_arena_getter_for_msgmut$ $accessor_fns_for_muts$ @@ -1248,10 +1259,6 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { $Msg$Mut::new($pbi$::Private, &mut self.inner) } - pub fn merge_from<'src>(&mut self, src: impl $pb$::Proxy<'src, Proxied = $Msg$>) { - self.as_mut().merge_from(src); - } - $accessor_fns$ } // impl $Msg$