Replace CreateMaybeMessage hooks with a `void*` based signature to allow
reusing the functions in more generic contexts.
Reuse these new functions in the implementation of RepeatedPtrField.

PiperOrigin-RevId: 580530262
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index c4f8f5f..4370990 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -223,13 +223,23 @@
   // allocation protocol, documented above.
   template <typename T, typename... Args>
   PROTOBUF_ALWAYS_INLINE static T* CreateMessage(Arena* arena, Args&&... args) {
+    using Type = std::remove_const_t<T>;
     static_assert(
-        is_arena_constructable<T>::value,
+        is_arena_constructable<Type>::value,
         "CreateMessage can only construct types that are ArenaConstructable");
-    // We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal()
-    // because protobuf generated classes specialize CreateMaybeMessage() and we
-    // need to use that specialization for code size reasons.
-    return Arena::CreateMaybeMessage<T>(arena, static_cast<Args&&>(args)...);
+#ifdef __cpp_if_constexpr
+    constexpr auto construct_type = GetConstructType<T, Args&&...>();
+    // We delegate to DefaultConstruct/CopyConstruct where appropriate
+    // because protobuf generated classes have external templates for these
+    // functions for code size reasons.
+    // When `if constexpr` is not available always use the fallback.
+    if constexpr (construct_type == ConstructType::kDefault) {
+      return static_cast<Type*>(DefaultConstruct<Type>(arena));
+    } else if constexpr (construct_type == ConstructType::kCopy) {
+      return static_cast<Type*>(CopyConstruct<Type>(arena, &args...));
+    }
+#endif
+    return CreateMessageInternal<Type>(arena, std::forward<Args>(args)...);
   }
 
   // API to create any objects on the arena. Note that only the object will
@@ -471,6 +481,36 @@
  private:
   internal::ThreadSafeArena impl_;
 
+  enum class ConstructType { kUnknown, kDefault, kCopy, kMove };
+  // Overload set to detect which kind of construction is going to happen for a
+  // specific set of input arguments. This is used to dispatch to different
+  // helper functions.
+  template <typename T>
+  static auto ProbeConstructType()
+      -> std::integral_constant<ConstructType, ConstructType::kDefault>;
+  template <typename T>
+  static auto ProbeConstructType(const T&)
+      -> std::integral_constant<ConstructType, ConstructType::kCopy>;
+  template <typename T>
+  static auto ProbeConstructType(T&)
+      -> std::integral_constant<ConstructType, ConstructType::kCopy>;
+  template <typename T>
+  static auto ProbeConstructType(const T&&)
+      -> std::integral_constant<ConstructType, ConstructType::kCopy>;
+  template <typename T>
+  static auto ProbeConstructType(T&&)
+      -> std::integral_constant<ConstructType, ConstructType::kMove>;
+  template <typename T, typename... U>
+  static auto ProbeConstructType(U&&...)
+      -> std::integral_constant<ConstructType, ConstructType::kUnknown>;
+
+  template <typename T, typename... Args>
+  static constexpr auto GetConstructType() {
+    return std::is_base_of<MessageLite, T>::value
+               ? decltype(ProbeConstructType<T>(std::declval<Args>()...))::value
+               : ConstructType::kUnknown;
+  }
+
   void ReturnArrayMemory(void* p, size_t size) {
     impl_.ReturnArrayMemory(p, size);
   }
@@ -517,31 +557,21 @@
     }
   }
 
-  // CreateMessage<T> requires that T supports arenas, but this private method
-  // works whether or not T supports arenas. These are not exposed to user code
-  // as it can cause confusing API usages, and end up having double free in
-  // user code. These are used only internally from LazyField and Repeated
-  // fields, since they are designed to work in all mode combinations.
-  template <typename Msg, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static Msg* DoCreateMaybeMessage(Arena* arena,
-                                                          std::true_type,
-                                                          Args&&... args) {
-    return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...);
-  }
-
-  template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static T* DoCreateMaybeMessage(Arena* arena,
-                                                        std::false_type,
-                                                        Args&&... args) {
-    return Create<T>(arena, std::forward<Args>(args)...);
-  }
-
-  template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena,
-                                                      Args&&... args) {
-    return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(),
-                                   std::forward<Args>(args)...);
-  }
+  // DefaultConstruct/CopyConstruct:
+  //
+  // Functions with a generic signature to support taking the address in generic
+  // contexts, like RepeatedPtrField, etc.
+  // These are also used as a hook for `extern template` instantiations where
+  // codegen can offload the instantiations to the respective .pb.cc files. This
+  // has two benefits:
+  //  - It reduces the library bloat as callers don't have to instantiate the
+  //  function.
+  //  - It allows the optimizer to see the constructors called to
+  //  further optimize the instantiation.
+  template <typename T>
+  static void* DefaultConstruct(Arena* arena);
+  template <typename T>
+  static void* CopyConstruct(Arena* arena, const void* from);
 
   template <typename T, typename... Args>
   PROTOBUF_NDEBUG_INLINE T* DoCreateMessage(Args&&... args) {
@@ -620,7 +650,7 @@
   template <typename Type>
   friend class internal::GenericTypeHandler;
   friend class internal::InternalMetadata;  // For user_arena().
-  friend class internal::LazyField;        // For CreateMaybeMessage.
+  friend class internal::LazyField;         // For DefaultConstruct.
   friend class internal::EpsCopyInputStream;  // For parser performance
   friend class internal::TcParser;            // For parser performance
   friend class MessageLite;
@@ -632,6 +662,24 @@
   friend struct internal::ArenaTestPeer;
 };
 
+// DefaultConstruct/CopyConstruct
+//
+// IMPORTANT: These have to be defined out of line and without an `inline`
+// keyword to make sure the `extern template` suppresses instantiations.
+template <typename T>
+PROTOBUF_NOINLINE void* Arena::DefaultConstruct(Arena* arena) {
+  void* mem = arena != nullptr ? arena->AllocateAligned(sizeof(T))
+                               : ::operator new(sizeof(T));
+  return new (mem) T(arena);
+}
+
+template <typename T>
+PROTOBUF_NOINLINE void* Arena::CopyConstruct(Arena* arena, const void* from) {
+  void* mem = arena != nullptr ? arena->AllocateAligned(sizeof(T))
+                               : ::operator new(sizeof(T));
+  return new (mem) T(arena, *static_cast<const T*>(from));
+}
+
 template <>
 inline void* Arena::AllocateInternal<std::string, false>() {
   return impl_.AllocateFromStringBlock();
diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h
index e2144a8..40b44c1 100644
--- a/src/google/protobuf/arena_test_util.h
+++ b/src/google/protobuf/arena_test_util.h
@@ -62,6 +62,11 @@
   static auto PeekCleanupListForTesting(Arena* arena) {
     return arena->PeekCleanupListForTesting();
   }
+  template <typename T, typename... U>
+  static constexpr auto GetConstructType() {
+    return Arena::GetConstructType<T, U...>();
+  }
+  using ConstructType = Arena::ConstructType;
 };
 
 struct CleanupGrowthInfo {
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index 2104112..673e3e6 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -17,11 +17,13 @@
 #include <thread>
 #include <type_traits>
 #include <typeinfo>
+#include <utility>
 #include <vector>
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include "absl/log/absl_check.h"
+#include "absl/log/absl_log.h"
 #include "absl/strings/string_view.h"
 #include "absl/synchronization/barrier.h"
 #include "google/protobuf/arena_test_util.h"
@@ -324,6 +326,81 @@
   Arena::CreateMessage<OnlyArenaConstructible>(&arena);
 }
 
+TEST(ArenaTest, GetConstructTypeWorks) {
+  using T = TestAllTypes;
+  using Peer = internal::ArenaTestPeer;
+  using CT = typename Peer::ConstructType;
+  EXPECT_EQ(CT::kDefault, (Peer::GetConstructType<T>()));
+  EXPECT_EQ(CT::kCopy, (Peer::GetConstructType<T, const T&>()));
+  EXPECT_EQ(CT::kCopy, (Peer::GetConstructType<T, T&>()));
+  EXPECT_EQ(CT::kCopy, (Peer::GetConstructType<T, const T&&>()));
+  EXPECT_EQ(CT::kMove, (Peer::GetConstructType<T, T&&>()));
+  EXPECT_EQ(CT::kUnknown, (Peer::GetConstructType<T, double&>()));
+  EXPECT_EQ(CT::kUnknown, (Peer::GetConstructType<T, T&, T&>()));
+
+  // For non-protos, it's always unknown
+  EXPECT_EQ(CT::kUnknown, (Peer::GetConstructType<int, const int&>()));
+}
+
+#ifdef __cpp_if_constexpr
+class DispatcherTestProto : public Message {
+ public:
+  using InternalArenaConstructable_ = void;
+  // For the test below to construct.
+  explicit DispatcherTestProto(absl::in_place_t) {}
+  explicit DispatcherTestProto(Arena*) { ABSL_LOG(FATAL); }
+  DispatcherTestProto(Arena*, const DispatcherTestProto&) { ABSL_LOG(FATAL); }
+  DispatcherTestProto* New(Arena*) const final { ABSL_LOG(FATAL); }
+  Metadata GetMetadata() const final { ABSL_LOG(FATAL); }
+  const ClassData* GetClassData() const final { ABSL_LOG(FATAL); }
+};
+// We use a specialization to inject behavior for the test.
+// This test is very intrusive and will have to be fixed if we change the
+// implementation of CreateMessage.
+absl::string_view hook_called;
+template <>
+void* Arena::DefaultConstruct<DispatcherTestProto>(Arena*) {
+  hook_called = "default";
+  return nullptr;
+}
+template <>
+void* Arena::CopyConstruct<DispatcherTestProto>(Arena*, const void*) {
+  hook_called = "copy";
+  return nullptr;
+}
+template <>
+DispatcherTestProto* Arena::CreateMessageInternal<DispatcherTestProto, int>(
+    Arena*, int&&) {
+  hook_called = "fallback";
+  return nullptr;
+}
+
+TEST(ArenaTest, CreateMessageDispatchesToSpecialFunctions) {
+  hook_called = "";
+  Arena::CreateMessage<DispatcherTestProto>(nullptr);
+  EXPECT_EQ(hook_called, "default");
+
+  DispatcherTestProto ref(absl::in_place);
+  const DispatcherTestProto& cref = ref;
+
+  hook_called = "";
+  Arena::CreateMessage<DispatcherTestProto>(nullptr);
+  EXPECT_EQ(hook_called, "default");
+
+  hook_called = "";
+  Arena::CreateMessage<DispatcherTestProto>(nullptr, ref);
+  EXPECT_EQ(hook_called, "copy");
+
+  hook_called = "";
+  Arena::CreateMessage<DispatcherTestProto>(nullptr, cref);
+  EXPECT_EQ(hook_called, "copy");
+
+  hook_called = "";
+  Arena::CreateMessage<DispatcherTestProto>(nullptr, 1);
+  EXPECT_EQ(hook_called, "fallback");
+}
+#endif  // __cpp_if_constexpr
+
 TEST(ArenaTest, Parsing) {
   TestAllTypes original;
   TestUtil::SetAllFields(&original);
diff --git a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc
index 83d2a21..e5ac613 100644
--- a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc
+++ b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc
@@ -133,12 +133,13 @@
   }
 
   void GenerateMemberCopyConstructor(io::Printer* p) const override {
-    p->Emit("$name$_{CreateMaybeMessage<$Submsg$>(arena, *from.$name$_)}");
+    p->Emit(
+        "$name$_{$superclass$::CopyConstruct<$Submsg$>(arena, *from.$name$_)}");
   }
 
   void GenerateOneofCopyConstruct(io::Printer* p) const override {
     p->Emit(R"cc(
-      $field$ = CreateMaybeMessage<$Submsg$>(arena, *from.$field$);
+      $field$ = $superclass$::CopyConstruct<$Submsg$>(arena, *from.$field$);
     )cc");
   }
 
@@ -262,7 +263,7 @@
           $StrongRef$;
           $set_hasbit$;
           if ($field_$ == nullptr) {
-            auto* p = CreateMaybeMessage<$Submsg$>(GetArena());
+            auto* p = $superclass$::DefaultConstruct<$Submsg$>(GetArena());
             $field_$ = reinterpret_cast<$MemberType$*>(p);
           }
           return $cast_field_$;
@@ -443,7 +444,8 @@
     p->Emit(R"cc(
       $DCHK$(from.$field_$ != nullptr);
       if (_this->$field_$ == nullptr) {
-        _this->$field_$ = CreateMaybeMessage<$Submsg$>(arena, *from.$field_$);
+        _this->$field_$ =
+            $superclass$::CopyConstruct<$Submsg$>(arena, *from.$field_$);
       } else {
         _this->$field_$->MergeFrom(*from.$field_$);
       }
@@ -474,13 +476,15 @@
   if (has_hasbit_) {
     p->Emit(R"cc(
       if ((from.$has_hasbit$) != 0) {
-        _this->$field_$ = CreateMaybeMessage<$Submsg$>(arena, *from.$field_$);
+        _this->$field_$ =
+            $superclass$::CopyConstruct<$Submsg$>(arena, *from.$field_$);
       }
     )cc");
   } else {
     p->Emit(R"cc(
       if (from._internal_has_$name$()) {
-        _this->$field_$ = CreateMaybeMessage<$Submsg$>(arena, *from.$field_$);
+        _this->$field_$ =
+            $superclass$::CopyConstruct<$Submsg$>(arena, *from.$field_$);
       }
     )cc");
   }
@@ -661,7 +665,8 @@
       if ($not_has_field$) {
         clear_$oneof_name$();
         set_has_$name$();
-        $field_$ = $weak_cast$(CreateMaybeMessage<$Submsg$>(GetArena()));
+        $field_$ =
+            $weak_cast$($superclass$::DefaultConstruct<$Submsg$>(GetArena()));
       }
       return $cast_field_$;
     }
@@ -855,9 +860,8 @@
         $TsanDetectConcurrentRead$;
         $PrepareSplitMessageForWrite$;
         if ($field_$.IsDefault()) {
-          $field_$.Set(
-              CreateMaybeMessage<$pb$::$Weak$RepeatedPtrField<$Submsg$>>(
-                  GetArena()));
+          $field_$.Set($superclass$::DefaultConstruct<
+                       $pb$::$Weak$RepeatedPtrField<$Submsg$>>(GetArena()));
         }
         return $field_$.Get();
       }
diff --git a/src/google/protobuf/compiler/cpp/file.cc b/src/google/protobuf/compiler/cpp/file.cc
index 1c88b8a..a70ea0b 100644
--- a/src/google/protobuf/compiler/cpp/file.cc
+++ b/src/google/protobuf/compiler/cpp/file.cc
@@ -1405,14 +1405,12 @@
         // However, it increases the size of the pb.cc translation units so it
         // is a tradeoff.
         p->Emit({{"class", QualifiedClassName(c.second, options)}}, R"cc(
-          template <>
-          $dllexport_decl $$class$* Arena::CreateMaybeMessage<$class$>(Arena*);
+          extern template void* Arena::DefaultConstruct<$class$>(Arena*);
         )cc");
         if (!IsMapEntryMessage(c.second)) {
           p->Emit({{"class", QualifiedClassName(c.second, options)}}, R"cc(
-            template <>
-            $dllexport_decl $$class$* Arena::CreateMaybeMessage<$class$>(
-                Arena*, const $class$&);
+            extern template void* Arena::CopyConstruct<$class$>(Arena*,
+                                                                const void*);
           )cc");
         }
       }
diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc
index 8dfff78..0c41a5e 100644
--- a/src/google/protobuf/compiler/cpp/message.cc
+++ b/src/google/protobuf/compiler/cpp/message.cc
@@ -1477,7 +1477,7 @@
       "// implements Message ----------------------------------------------\n"
       "\n"
       "$classname$* New(::$proto_ns$::Arena* arena = nullptr) const final {\n"
-      "  return CreateMaybeMessage<$classname$>(arena);\n"
+      "  return $superclass$::DefaultConstruct<$classname$>(arena);\n"
       "}\n");
 
   // For instances that derive from Message (rather than MessageLite), some
@@ -2739,9 +2739,9 @@
     p->Emit({{"has_msg", [&] { has_message(field); }},
              {"submsg", FieldMessageTypeName(field, options_)}},
             R"cc(
-              $field$ = ($has_msg$)
-                            ? CreateMaybeMessage<$submsg$>(arena, *from.$field$)
-                            : nullptr;
+              $field$ = ($has_msg$) ? $superclass$::CopyConstruct<$submsg$>(
+                                          arena, *from.$field$)
+                                    : nullptr;
             )cc");
   };
 
@@ -3000,26 +3000,12 @@
   Formatter format(p);
   if (ShouldGenerateExternSpecializations(options_) &&
       ShouldGenerateClass(descriptor_, options_)) {
-    format(R"cc(
-      template <>
-      PROTOBUF_NOINLINE $classtype$* Arena::CreateMaybeMessage<$classtype$>(
-          Arena* arena) {
-        using T = $classtype$;
-        void* mem = arena != nullptr ? arena->AllocateAligned(sizeof(T))
-                                     : ::operator new(sizeof(T));
-        return new (mem) T(arena);
-      }
+    p->Emit(R"cc(
+      template void* Arena::DefaultConstruct<$classtype$>(Arena*);
     )cc");
     if (!IsMapEntryMessage(descriptor_)) {
-      format(R"cc(
-        template <>
-        PROTOBUF_NOINLINE $classtype$* Arena::CreateMaybeMessage<$classtype$>(
-            Arena* arena, const $classtype$& from) {
-          using T = $classtype$;
-          void* mem = arena != nullptr ? arena->AllocateAligned(sizeof(T))
-                                       : ::operator new(sizeof(T));
-          return new (mem) T(arena, from);
-        }
+      p->Emit(R"cc(
+        template void* Arena::CopyConstruct<$classtype$>(Arena*, const void*);
       )cc");
     }
   }
diff --git a/src/google/protobuf/compiler/java/java_features.pb.h b/src/google/protobuf/compiler/java/java_features.pb.h
index e4b0a51..e57275a 100644
--- a/src/google/protobuf/compiler/java/java_features.pb.h
+++ b/src/google/protobuf/compiler/java/java_features.pb.h
@@ -190,7 +190,7 @@
   // implements Message ----------------------------------------------
 
   JavaFeatures* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<JavaFeatures>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<JavaFeatures>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const JavaFeatures& from);
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index dc37bd6..17247ab 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -665,9 +665,9 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.compiler_version_ = (cached_has_bits & 0x00000002u)
-                ? CreateMaybeMessage<::google::protobuf::compiler::Version>(arena, *from._impl_.compiler_version_)
-                : nullptr;
+  _impl_.compiler_version_ = (cached_has_bits & 0x00000002u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::compiler::Version>(
+                              arena, *from._impl_.compiler_version_)
+                        : nullptr;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest)
 }
@@ -922,7 +922,8 @@
     if (cached_has_bits & 0x00000002u) {
       ABSL_DCHECK(from._impl_.compiler_version_ != nullptr);
       if (_this->_impl_.compiler_version_ == nullptr) {
-        _this->_impl_.compiler_version_ = CreateMaybeMessage<::google::protobuf::compiler::Version>(arena, *from._impl_.compiler_version_);
+        _this->_impl_.compiler_version_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::compiler::Version>(arena, *from._impl_.compiler_version_);
       } else {
         _this->_impl_.compiler_version_->MergeFrom(*from._impl_.compiler_version_);
       }
@@ -1019,9 +1020,9 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.generated_code_info_ = (cached_has_bits & 0x00000008u)
-                ? CreateMaybeMessage<::google::protobuf::GeneratedCodeInfo>(arena, *from._impl_.generated_code_info_)
-                : nullptr;
+  _impl_.generated_code_info_ = (cached_has_bits & 0x00000008u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::GeneratedCodeInfo>(
+                              arena, *from._impl_.generated_code_info_)
+                        : nullptr;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
 }
@@ -1259,7 +1260,8 @@
     if (cached_has_bits & 0x00000008u) {
       ABSL_DCHECK(from._impl_.generated_code_info_ != nullptr);
       if (_this->_impl_.generated_code_info_ == nullptr) {
-        _this->_impl_.generated_code_info_ = CreateMaybeMessage<::google::protobuf::GeneratedCodeInfo>(arena, *from._impl_.generated_code_info_);
+        _this->_impl_.generated_code_info_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::GeneratedCodeInfo>(arena, *from._impl_.generated_code_info_);
       } else {
         _this->_impl_.generated_code_info_->MergeFrom(*from._impl_.generated_code_info_);
       }
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index d4d3613..e48dbb6 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -207,7 +207,7 @@
   // implements Message ----------------------------------------------
 
   Version* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<Version>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<Version>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const Version& from);
@@ -426,7 +426,7 @@
   // implements Message ----------------------------------------------
 
   CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<CodeGeneratorResponse_File>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<CodeGeneratorResponse_File>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const CodeGeneratorResponse_File& from);
@@ -661,7 +661,7 @@
   // implements Message ----------------------------------------------
 
   CodeGeneratorResponse* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<CodeGeneratorResponse>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<CodeGeneratorResponse>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const CodeGeneratorResponse& from);
@@ -897,7 +897,7 @@
   // implements Message ----------------------------------------------
 
   CodeGeneratorRequest* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<CodeGeneratorRequest>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<CodeGeneratorRequest>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const CodeGeneratorRequest& from);
@@ -1580,7 +1580,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000002u;
   if (_impl_.compiler_version_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::compiler::Version>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::compiler::Version>(GetArena());
     _impl_.compiler_version_ = reinterpret_cast<::google::protobuf::compiler::Version*>(p);
   }
   return _impl_.compiler_version_;
@@ -1888,7 +1888,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000008u;
   if (_impl_.generated_code_info_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::GeneratedCodeInfo>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::GeneratedCodeInfo>(GetArena());
     _impl_.generated_code_info_ = reinterpret_cast<::google::protobuf::GeneratedCodeInfo*>(p);
   }
   return _impl_.generated_code_info_;
diff --git a/src/google/protobuf/cpp_features.pb.h b/src/google/protobuf/cpp_features.pb.h
index c06083e..cab376f 100644
--- a/src/google/protobuf/cpp_features.pb.h
+++ b/src/google/protobuf/cpp_features.pb.h
@@ -159,7 +159,7 @@
   // implements Message ----------------------------------------------
 
   CppFeatures* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<CppFeatures>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<CppFeatures>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const CppFeatures& from);
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index a900687..0a33adf 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -2599,12 +2599,12 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.options_ = (cached_has_bits & 0x00000008u)
-                ? CreateMaybeMessage<::google::protobuf::FileOptions>(arena, *from._impl_.options_)
-                : nullptr;
-  _impl_.source_code_info_ = (cached_has_bits & 0x00000010u)
-                ? CreateMaybeMessage<::google::protobuf::SourceCodeInfo>(arena, *from._impl_.source_code_info_)
-                : nullptr;
+  _impl_.options_ = (cached_has_bits & 0x00000008u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FileOptions>(
+                              arena, *from._impl_.options_)
+                        : nullptr;
+  _impl_.source_code_info_ = (cached_has_bits & 0x00000010u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceCodeInfo>(
+                              arena, *from._impl_.source_code_info_)
+                        : nullptr;
   _impl_.edition_ = from._impl_.edition_;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorProto)
@@ -3072,7 +3072,8 @@
     if (cached_has_bits & 0x00000008u) {
       ABSL_DCHECK(from._impl_.options_ != nullptr);
       if (_this->_impl_.options_ == nullptr) {
-        _this->_impl_.options_ = CreateMaybeMessage<::google::protobuf::FileOptions>(arena, *from._impl_.options_);
+        _this->_impl_.options_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::FileOptions>(arena, *from._impl_.options_);
       } else {
         _this->_impl_.options_->MergeFrom(*from._impl_.options_);
       }
@@ -3081,7 +3082,8 @@
     if (cached_has_bits & 0x00000010u) {
       ABSL_DCHECK(from._impl_.source_code_info_ != nullptr);
       if (_this->_impl_.source_code_info_ == nullptr) {
-        _this->_impl_.source_code_info_ = CreateMaybeMessage<::google::protobuf::SourceCodeInfo>(arena, *from._impl_.source_code_info_);
+        _this->_impl_.source_code_info_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceCodeInfo>(arena, *from._impl_.source_code_info_);
       } else {
         _this->_impl_.source_code_info_->MergeFrom(*from._impl_.source_code_info_);
       }
@@ -3189,9 +3191,9 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.options_ = (cached_has_bits & 0x00000001u)
-                ? CreateMaybeMessage<::google::protobuf::ExtensionRangeOptions>(arena, *from._impl_.options_)
-                : nullptr;
+  _impl_.options_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::ExtensionRangeOptions>(
+                              arena, *from._impl_.options_)
+                        : nullptr;
   ::memcpy(reinterpret_cast<char *>(&_impl_) +
                offsetof(Impl_, start_),
            reinterpret_cast<const char *>(&from._impl_) +
@@ -3393,7 +3395,8 @@
     if (cached_has_bits & 0x00000001u) {
       ABSL_DCHECK(from._impl_.options_ != nullptr);
       if (_this->_impl_.options_ == nullptr) {
-        _this->_impl_.options_ = CreateMaybeMessage<::google::protobuf::ExtensionRangeOptions>(arena, *from._impl_.options_);
+        _this->_impl_.options_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::ExtensionRangeOptions>(arena, *from._impl_.options_);
       } else {
         _this->_impl_.options_->MergeFrom(*from._impl_.options_);
       }
@@ -3716,9 +3719,9 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.options_ = (cached_has_bits & 0x00000002u)
-                ? CreateMaybeMessage<::google::protobuf::MessageOptions>(arena, *from._impl_.options_)
-                : nullptr;
+  _impl_.options_ = (cached_has_bits & 0x00000002u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::MessageOptions>(
+                              arena, *from._impl_.options_)
+                        : nullptr;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto)
 }
@@ -4102,7 +4105,8 @@
     if (cached_has_bits & 0x00000002u) {
       ABSL_DCHECK(from._impl_.options_ != nullptr);
       if (_this->_impl_.options_ == nullptr) {
-        _this->_impl_.options_ = CreateMaybeMessage<::google::protobuf::MessageOptions>(arena, *from._impl_.options_);
+        _this->_impl_.options_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::MessageOptions>(arena, *from._impl_.options_);
       } else {
         _this->_impl_.options_->MergeFrom(*from._impl_.options_);
       }
@@ -4551,9 +4555,9 @@
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   _impl_._extensions_.MergeFrom(this, from._impl_._extensions_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.features_ = (cached_has_bits & 0x00000001u)
-                ? CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_)
-                : nullptr;
+  _impl_.features_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(
+                              arena, *from._impl_.features_)
+                        : nullptr;
   _impl_.verification_ = from._impl_.verification_;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.ExtensionRangeOptions)
@@ -4786,7 +4790,8 @@
     if (cached_has_bits & 0x00000001u) {
       ABSL_DCHECK(from._impl_.features_ != nullptr);
       if (_this->_impl_.features_ == nullptr) {
-        _this->_impl_.features_ = CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
+        _this->_impl_.features_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
       } else {
         _this->_impl_.features_->MergeFrom(*from._impl_.features_);
       }
@@ -4912,9 +4917,9 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.options_ = (cached_has_bits & 0x00000020u)
-                ? CreateMaybeMessage<::google::protobuf::FieldOptions>(arena, *from._impl_.options_)
-                : nullptr;
+  _impl_.options_ = (cached_has_bits & 0x00000020u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FieldOptions>(
+                              arena, *from._impl_.options_)
+                        : nullptr;
   ::memcpy(reinterpret_cast<char *>(&_impl_) +
                offsetof(Impl_, number_),
            reinterpret_cast<const char *>(&from._impl_) +
@@ -5334,7 +5339,8 @@
     if (cached_has_bits & 0x00000020u) {
       ABSL_DCHECK(from._impl_.options_ != nullptr);
       if (_this->_impl_.options_ == nullptr) {
-        _this->_impl_.options_ = CreateMaybeMessage<::google::protobuf::FieldOptions>(arena, *from._impl_.options_);
+        _this->_impl_.options_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::FieldOptions>(arena, *from._impl_.options_);
       } else {
         _this->_impl_.options_->MergeFrom(*from._impl_.options_);
       }
@@ -5442,9 +5448,9 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.options_ = (cached_has_bits & 0x00000002u)
-                ? CreateMaybeMessage<::google::protobuf::OneofOptions>(arena, *from._impl_.options_)
-                : nullptr;
+  _impl_.options_ = (cached_has_bits & 0x00000002u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::OneofOptions>(
+                              arena, *from._impl_.options_)
+                        : nullptr;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofDescriptorProto)
 }
@@ -5623,7 +5629,8 @@
     if (cached_has_bits & 0x00000002u) {
       ABSL_DCHECK(from._impl_.options_ != nullptr);
       if (_this->_impl_.options_ == nullptr) {
-        _this->_impl_.options_ = CreateMaybeMessage<::google::protobuf::OneofOptions>(arena, *from._impl_.options_);
+        _this->_impl_.options_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::OneofOptions>(arena, *from._impl_.options_);
       } else {
         _this->_impl_.options_->MergeFrom(*from._impl_.options_);
       }
@@ -5932,9 +5939,9 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.options_ = (cached_has_bits & 0x00000002u)
-                ? CreateMaybeMessage<::google::protobuf::EnumOptions>(arena, *from._impl_.options_)
-                : nullptr;
+  _impl_.options_ = (cached_has_bits & 0x00000002u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::EnumOptions>(
+                              arena, *from._impl_.options_)
+                        : nullptr;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto)
 }
@@ -6190,7 +6197,8 @@
     if (cached_has_bits & 0x00000002u) {
       ABSL_DCHECK(from._impl_.options_ != nullptr);
       if (_this->_impl_.options_ == nullptr) {
-        _this->_impl_.options_ = CreateMaybeMessage<::google::protobuf::EnumOptions>(arena, *from._impl_.options_);
+        _this->_impl_.options_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::EnumOptions>(arena, *from._impl_.options_);
       } else {
         _this->_impl_.options_->MergeFrom(*from._impl_.options_);
       }
@@ -6278,9 +6286,9 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.options_ = (cached_has_bits & 0x00000002u)
-                ? CreateMaybeMessage<::google::protobuf::EnumValueOptions>(arena, *from._impl_.options_)
-                : nullptr;
+  _impl_.options_ = (cached_has_bits & 0x00000002u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::EnumValueOptions>(
+                              arena, *from._impl_.options_)
+                        : nullptr;
   _impl_.number_ = from._impl_.number_;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueDescriptorProto)
@@ -6486,7 +6494,8 @@
     if (cached_has_bits & 0x00000002u) {
       ABSL_DCHECK(from._impl_.options_ != nullptr);
       if (_this->_impl_.options_ == nullptr) {
-        _this->_impl_.options_ = CreateMaybeMessage<::google::protobuf::EnumValueOptions>(arena, *from._impl_.options_);
+        _this->_impl_.options_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::EnumValueOptions>(arena, *from._impl_.options_);
       } else {
         _this->_impl_.options_->MergeFrom(*from._impl_.options_);
       }
@@ -6576,9 +6585,9 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.options_ = (cached_has_bits & 0x00000002u)
-                ? CreateMaybeMessage<::google::protobuf::ServiceOptions>(arena, *from._impl_.options_)
-                : nullptr;
+  _impl_.options_ = (cached_has_bits & 0x00000002u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::ServiceOptions>(
+                              arena, *from._impl_.options_)
+                        : nullptr;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceDescriptorProto)
 }
@@ -6783,7 +6792,8 @@
     if (cached_has_bits & 0x00000002u) {
       ABSL_DCHECK(from._impl_.options_ != nullptr);
       if (_this->_impl_.options_ == nullptr) {
-        _this->_impl_.options_ = CreateMaybeMessage<::google::protobuf::ServiceOptions>(arena, *from._impl_.options_);
+        _this->_impl_.options_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::ServiceOptions>(arena, *from._impl_.options_);
       } else {
         _this->_impl_.options_->MergeFrom(*from._impl_.options_);
       }
@@ -6880,9 +6890,9 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.options_ = (cached_has_bits & 0x00000008u)
-                ? CreateMaybeMessage<::google::protobuf::MethodOptions>(arena, *from._impl_.options_)
-                : nullptr;
+  _impl_.options_ = (cached_has_bits & 0x00000008u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::MethodOptions>(
+                              arena, *from._impl_.options_)
+                        : nullptr;
   ::memcpy(reinterpret_cast<char *>(&_impl_) +
                offsetof(Impl_, client_streaming_),
            reinterpret_cast<const char *>(&from._impl_) +
@@ -7172,7 +7182,8 @@
     if (cached_has_bits & 0x00000008u) {
       ABSL_DCHECK(from._impl_.options_ != nullptr);
       if (_this->_impl_.options_ == nullptr) {
-        _this->_impl_.options_ = CreateMaybeMessage<::google::protobuf::MethodOptions>(arena, *from._impl_.options_);
+        _this->_impl_.options_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::MethodOptions>(arena, *from._impl_.options_);
       } else {
         _this->_impl_.options_->MergeFrom(*from._impl_.options_);
       }
@@ -7335,9 +7346,9 @@
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   _impl_._extensions_.MergeFrom(this, from._impl_._extensions_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.features_ = (cached_has_bits & 0x00000400u)
-                ? CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_)
-                : nullptr;
+  _impl_.features_ = (cached_has_bits & 0x00000400u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(
+                              arena, *from._impl_.features_)
+                        : nullptr;
   ::memcpy(reinterpret_cast<char *>(&_impl_) +
                offsetof(Impl_, java_multiple_files_),
            reinterpret_cast<const char *>(&from._impl_) +
@@ -8030,7 +8041,8 @@
     if (cached_has_bits & 0x00000400u) {
       ABSL_DCHECK(from._impl_.features_ != nullptr);
       if (_this->_impl_.features_ == nullptr) {
-        _this->_impl_.features_ = CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
+        _this->_impl_.features_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
       } else {
         _this->_impl_.features_->MergeFrom(*from._impl_.features_);
       }
@@ -8180,9 +8192,9 @@
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   _impl_._extensions_.MergeFrom(this, from._impl_._extensions_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.features_ = (cached_has_bits & 0x00000001u)
-                ? CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_)
-                : nullptr;
+  _impl_.features_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(
+                              arena, *from._impl_.features_)
+                        : nullptr;
   ::memcpy(reinterpret_cast<char *>(&_impl_) +
                offsetof(Impl_, message_set_wire_format_),
            reinterpret_cast<const char *>(&from._impl_) +
@@ -8466,7 +8478,8 @@
     if (cached_has_bits & 0x00000001u) {
       ABSL_DCHECK(from._impl_.features_ != nullptr);
       if (_this->_impl_.features_ == nullptr) {
-        _this->_impl_.features_ = CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
+        _this->_impl_.features_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
       } else {
         _this->_impl_.features_->MergeFrom(*from._impl_.features_);
       }
@@ -8839,9 +8852,9 @@
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   _impl_._extensions_.MergeFrom(this, from._impl_._extensions_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.features_ = (cached_has_bits & 0x00000001u)
-                ? CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_)
-                : nullptr;
+  _impl_.features_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(
+                              arena, *from._impl_.features_)
+                        : nullptr;
   ::memcpy(reinterpret_cast<char *>(&_impl_) +
                offsetof(Impl_, ctype_),
            reinterpret_cast<const char *>(&from._impl_) +
@@ -9265,7 +9278,8 @@
     if (cached_has_bits & 0x00000001u) {
       ABSL_DCHECK(from._impl_.features_ != nullptr);
       if (_this->_impl_.features_ == nullptr) {
-        _this->_impl_.features_ = CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
+        _this->_impl_.features_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
       } else {
         _this->_impl_.features_->MergeFrom(*from._impl_.features_);
       }
@@ -9387,9 +9401,9 @@
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   _impl_._extensions_.MergeFrom(this, from._impl_._extensions_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.features_ = (cached_has_bits & 0x00000001u)
-                ? CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_)
-                : nullptr;
+  _impl_.features_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(
+                              arena, *from._impl_.features_)
+                        : nullptr;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofOptions)
 }
@@ -9567,7 +9581,8 @@
   if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     ABSL_DCHECK(from._impl_.features_ != nullptr);
     if (_this->_impl_.features_ == nullptr) {
-      _this->_impl_.features_ = CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
+      _this->_impl_.features_ =
+          ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
     } else {
       _this->_impl_.features_->MergeFrom(*from._impl_.features_);
     }
@@ -9659,9 +9674,9 @@
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   _impl_._extensions_.MergeFrom(this, from._impl_._extensions_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.features_ = (cached_has_bits & 0x00000001u)
-                ? CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_)
-                : nullptr;
+  _impl_.features_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(
+                              arena, *from._impl_.features_)
+                        : nullptr;
   ::memcpy(reinterpret_cast<char *>(&_impl_) +
                offsetof(Impl_, allow_alias_),
            reinterpret_cast<const char *>(&from._impl_) +
@@ -9911,7 +9926,8 @@
     if (cached_has_bits & 0x00000001u) {
       ABSL_DCHECK(from._impl_.features_ != nullptr);
       if (_this->_impl_.features_ == nullptr) {
-        _this->_impl_.features_ = CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
+        _this->_impl_.features_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
       } else {
         _this->_impl_.features_->MergeFrom(*from._impl_.features_);
       }
@@ -10016,9 +10032,9 @@
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   _impl_._extensions_.MergeFrom(this, from._impl_._extensions_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.features_ = (cached_has_bits & 0x00000001u)
-                ? CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_)
-                : nullptr;
+  _impl_.features_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(
+                              arena, *from._impl_.features_)
+                        : nullptr;
   ::memcpy(reinterpret_cast<char *>(&_impl_) +
                offsetof(Impl_, deprecated_),
            reinterpret_cast<const char *>(&from._impl_) +
@@ -10253,7 +10269,8 @@
     if (cached_has_bits & 0x00000001u) {
       ABSL_DCHECK(from._impl_.features_ != nullptr);
       if (_this->_impl_.features_ == nullptr) {
-        _this->_impl_.features_ = CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
+        _this->_impl_.features_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
       } else {
         _this->_impl_.features_->MergeFrom(*from._impl_.features_);
       }
@@ -10352,9 +10369,9 @@
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   _impl_._extensions_.MergeFrom(this, from._impl_._extensions_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.features_ = (cached_has_bits & 0x00000001u)
-                ? CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_)
-                : nullptr;
+  _impl_.features_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(
+                              arena, *from._impl_.features_)
+                        : nullptr;
   _impl_.deprecated_ = from._impl_.deprecated_;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceOptions)
@@ -10561,7 +10578,8 @@
     if (cached_has_bits & 0x00000001u) {
       ABSL_DCHECK(from._impl_.features_ != nullptr);
       if (_this->_impl_.features_ == nullptr) {
-        _this->_impl_.features_ = CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
+        _this->_impl_.features_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
       } else {
         _this->_impl_.features_->MergeFrom(*from._impl_.features_);
       }
@@ -10660,9 +10678,9 @@
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   _impl_._extensions_.MergeFrom(this, from._impl_._extensions_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.features_ = (cached_has_bits & 0x00000001u)
-                ? CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_)
-                : nullptr;
+  _impl_.features_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(
+                              arena, *from._impl_.features_)
+                        : nullptr;
   ::memcpy(reinterpret_cast<char *>(&_impl_) +
                offsetof(Impl_, deprecated_),
            reinterpret_cast<const char *>(&from._impl_) +
@@ -10902,7 +10920,8 @@
     if (cached_has_bits & 0x00000001u) {
       ABSL_DCHECK(from._impl_.features_ != nullptr);
       if (_this->_impl_.features_ == nullptr) {
-        _this->_impl_.features_ = CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
+        _this->_impl_.features_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
       } else {
         _this->_impl_.features_->MergeFrom(*from._impl_.features_);
       }
@@ -12013,9 +12032,9 @@
       from._internal_metadata_);
   new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
   ::uint32_t cached_has_bits = _impl_._has_bits_[0];
-  _impl_.features_ = (cached_has_bits & 0x00000001u)
-                ? CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_)
-                : nullptr;
+  _impl_.features_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(
+                              arena, *from._impl_.features_)
+                        : nullptr;
   _impl_.edition_ = from._impl_.edition_;
 
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault)
@@ -12188,7 +12207,8 @@
     if (cached_has_bits & 0x00000001u) {
       ABSL_DCHECK(from._impl_.features_ != nullptr);
       if (_this->_impl_.features_ == nullptr) {
-        _this->_impl_.features_ = CreateMaybeMessage<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
+        _this->_impl_.features_ =
+            ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>(arena, *from._impl_.features_);
       } else {
         _this->_impl_.features_->MergeFrom(*from._impl_.features_);
       }
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 5a0ab74..658988e 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -788,7 +788,7 @@
   // implements Message ----------------------------------------------
 
   UninterpretedOption_NamePart* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<UninterpretedOption_NamePart>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<UninterpretedOption_NamePart>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const UninterpretedOption_NamePart& from);
@@ -981,7 +981,7 @@
   // implements Message ----------------------------------------------
 
   SourceCodeInfo_Location* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<SourceCodeInfo_Location>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<SourceCodeInfo_Location>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const SourceCodeInfo_Location& from);
@@ -1252,7 +1252,7 @@
   // implements Message ----------------------------------------------
 
   GeneratedCodeInfo_Annotation* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<GeneratedCodeInfo_Annotation>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<GeneratedCodeInfo_Annotation>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const GeneratedCodeInfo_Annotation& from);
@@ -1513,7 +1513,7 @@
   // implements Message ----------------------------------------------
 
   FieldOptions_EditionDefault* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<FieldOptions_EditionDefault>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<FieldOptions_EditionDefault>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const FieldOptions_EditionDefault& from);
@@ -1706,7 +1706,7 @@
   // implements Message ----------------------------------------------
 
   FeatureSet* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<FeatureSet>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<FeatureSet>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const FeatureSet& from);
@@ -2251,7 +2251,7 @@
   // implements Message ----------------------------------------------
 
   ExtensionRangeOptions_Declaration* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<ExtensionRangeOptions_Declaration>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<ExtensionRangeOptions_Declaration>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const ExtensionRangeOptions_Declaration& from);
@@ -2489,7 +2489,7 @@
   // implements Message ----------------------------------------------
 
   EnumDescriptorProto_EnumReservedRange* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<EnumDescriptorProto_EnumReservedRange>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<EnumDescriptorProto_EnumReservedRange>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const EnumDescriptorProto_EnumReservedRange& from);
@@ -2676,7 +2676,7 @@
   // implements Message ----------------------------------------------
 
   DescriptorProto_ReservedRange* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<DescriptorProto_ReservedRange>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<DescriptorProto_ReservedRange>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const DescriptorProto_ReservedRange& from);
@@ -2863,7 +2863,7 @@
   // implements Message ----------------------------------------------
 
   UninterpretedOption* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<UninterpretedOption>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<UninterpretedOption>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const UninterpretedOption& from);
@@ -3142,7 +3142,7 @@
   // implements Message ----------------------------------------------
 
   SourceCodeInfo* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<SourceCodeInfo>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<SourceCodeInfo>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const SourceCodeInfo& from);
@@ -3324,7 +3324,7 @@
   // implements Message ----------------------------------------------
 
   GeneratedCodeInfo* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<GeneratedCodeInfo>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<GeneratedCodeInfo>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const GeneratedCodeInfo& from);
@@ -3506,7 +3506,7 @@
   // implements Message ----------------------------------------------
 
   FeatureSetDefaults_FeatureSetEditionDefault* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<FeatureSetDefaults_FeatureSetEditionDefault>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<FeatureSetDefaults_FeatureSetEditionDefault>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const FeatureSetDefaults_FeatureSetEditionDefault& from);
@@ -3697,7 +3697,7 @@
   // implements Message ----------------------------------------------
 
   ServiceOptions* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<ServiceOptions>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<ServiceOptions>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const ServiceOptions& from);
@@ -4087,7 +4087,7 @@
   // implements Message ----------------------------------------------
 
   OneofOptions* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<OneofOptions>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<OneofOptions>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const OneofOptions& from);
@@ -4464,7 +4464,7 @@
   // implements Message ----------------------------------------------
 
   MethodOptions* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<MethodOptions>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<MethodOptions>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const MethodOptions& from);
@@ -4888,7 +4888,7 @@
   // implements Message ----------------------------------------------
 
   MessageOptions* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<MessageOptions>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<MessageOptions>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const MessageOptions& from);
@@ -5330,7 +5330,7 @@
   // implements Message ----------------------------------------------
 
   FileOptions* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<FileOptions>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<FileOptions>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const FileOptions& from);
@@ -6048,7 +6048,7 @@
   // implements Message ----------------------------------------------
 
   FieldOptions* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<FieldOptions>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<FieldOptions>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const FieldOptions& from);
@@ -6676,7 +6676,7 @@
   // implements Message ----------------------------------------------
 
   FeatureSetDefaults* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<FeatureSetDefaults>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<FeatureSetDefaults>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const FeatureSetDefaults& from);
@@ -6885,7 +6885,7 @@
   // implements Message ----------------------------------------------
 
   ExtensionRangeOptions* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<ExtensionRangeOptions>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<ExtensionRangeOptions>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const ExtensionRangeOptions& from);
@@ -7317,7 +7317,7 @@
   // implements Message ----------------------------------------------
 
   EnumValueOptions* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<EnumValueOptions>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<EnumValueOptions>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const EnumValueOptions& from);
@@ -7720,7 +7720,7 @@
   // implements Message ----------------------------------------------
 
   EnumOptions* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<EnumOptions>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<EnumOptions>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const EnumOptions& from);
@@ -8136,7 +8136,7 @@
   // implements Message ----------------------------------------------
 
   OneofDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<OneofDescriptorProto>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<OneofDescriptorProto>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const OneofDescriptorProto& from);
@@ -8333,7 +8333,7 @@
   // implements Message ----------------------------------------------
 
   MethodDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<MethodDescriptorProto>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<MethodDescriptorProto>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const MethodDescriptorProto& from);
@@ -8594,7 +8594,7 @@
   // implements Message ----------------------------------------------
 
   FieldDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<FieldDescriptorProto>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<FieldDescriptorProto>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const FieldDescriptorProto& from);
@@ -8989,7 +8989,7 @@
   // implements Message ----------------------------------------------
 
   EnumValueDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<EnumValueDescriptorProto>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<EnumValueDescriptorProto>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const EnumValueDescriptorProto& from);
@@ -9199,7 +9199,7 @@
   // implements Message ----------------------------------------------
 
   DescriptorProto_ExtensionRange* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<DescriptorProto_ExtensionRange>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<DescriptorProto_ExtensionRange>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const DescriptorProto_ExtensionRange& from);
@@ -9403,7 +9403,7 @@
   // implements Message ----------------------------------------------
 
   ServiceDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<ServiceDescriptorProto>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<ServiceDescriptorProto>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const ServiceDescriptorProto& from);
@@ -9620,7 +9620,7 @@
   // implements Message ----------------------------------------------
 
   EnumDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<EnumDescriptorProto>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<EnumDescriptorProto>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const EnumDescriptorProto& from);
@@ -9889,7 +9889,7 @@
   // implements Message ----------------------------------------------
 
   DescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<DescriptorProto>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<DescriptorProto>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const DescriptorProto& from);
@@ -10259,7 +10259,7 @@
   // implements Message ----------------------------------------------
 
   FileDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<FileDescriptorProto>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<FileDescriptorProto>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const FileDescriptorProto& from);
@@ -10674,7 +10674,7 @@
   // implements Message ----------------------------------------------
 
   FileDescriptorSet* New(::google::protobuf::Arena* arena = nullptr) const final {
-    return CreateMaybeMessage<FileDescriptorSet>(arena);
+    return ::google::protobuf::Message::DefaultConstruct<FileDescriptorSet>(arena);
   }
   using ::google::protobuf::Message::CopyFrom;
   void CopyFrom(const FileDescriptorSet& from);
@@ -11431,7 +11431,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000008u;
   if (_impl_.options_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FileOptions>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FileOptions>(GetArena());
     _impl_.options_ = reinterpret_cast<::google::protobuf::FileOptions*>(p);
   }
   return _impl_.options_;
@@ -11527,7 +11527,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000010u;
   if (_impl_.source_code_info_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::SourceCodeInfo>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::SourceCodeInfo>(GetArena());
     _impl_.source_code_info_ = reinterpret_cast<::google::protobuf::SourceCodeInfo*>(p);
   }
   return _impl_.source_code_info_;
@@ -11783,7 +11783,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000001u;
   if (_impl_.options_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::ExtensionRangeOptions>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::ExtensionRangeOptions>(GetArena());
     _impl_.options_ = reinterpret_cast<::google::protobuf::ExtensionRangeOptions*>(p);
   }
   return _impl_.options_;
@@ -12308,7 +12308,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000002u;
   if (_impl_.options_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::MessageOptions>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::MessageOptions>(GetArena());
     _impl_.options_ = reinterpret_cast<::google::protobuf::MessageOptions*>(p);
   }
   return _impl_.options_;
@@ -12886,7 +12886,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000001u;
   if (_impl_.features_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FeatureSet>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FeatureSet>(GetArena());
     _impl_.features_ = reinterpret_cast<::google::protobuf::FeatureSet*>(p);
   }
   return _impl_.features_;
@@ -13484,7 +13484,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000020u;
   if (_impl_.options_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FieldOptions>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FieldOptions>(GetArena());
     _impl_.options_ = reinterpret_cast<::google::protobuf::FieldOptions*>(p);
   }
   return _impl_.options_;
@@ -13683,7 +13683,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000002u;
   if (_impl_.options_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::OneofOptions>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::OneofOptions>(GetArena());
     _impl_.options_ = reinterpret_cast<::google::protobuf::OneofOptions*>(p);
   }
   return _impl_.options_;
@@ -13963,7 +13963,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000002u;
   if (_impl_.options_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::EnumOptions>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::EnumOptions>(GetArena());
     _impl_.options_ = reinterpret_cast<::google::protobuf::EnumOptions*>(p);
   }
   return _impl_.options_;
@@ -14312,7 +14312,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000002u;
   if (_impl_.options_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::EnumValueOptions>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::EnumValueOptions>(GetArena());
     _impl_.options_ = reinterpret_cast<::google::protobuf::EnumValueOptions*>(p);
   }
   return _impl_.options_;
@@ -14532,7 +14532,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000002u;
   if (_impl_.options_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::ServiceOptions>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::ServiceOptions>(GetArena());
     _impl_.options_ = reinterpret_cast<::google::protobuf::ServiceOptions*>(p);
   }
   return _impl_.options_;
@@ -14845,7 +14845,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000008u;
   if (_impl_.options_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::MethodOptions>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::MethodOptions>(GetArena());
     _impl_.options_ = reinterpret_cast<::google::protobuf::MethodOptions*>(p);
   }
   return _impl_.options_;
@@ -15992,7 +15992,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000400u;
   if (_impl_.features_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FeatureSet>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FeatureSet>(GetArena());
     _impl_.features_ = reinterpret_cast<::google::protobuf::FeatureSet*>(p);
   }
   return _impl_.features_;
@@ -16281,7 +16281,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000001u;
   if (_impl_.features_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FeatureSet>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FeatureSet>(GetArena());
     _impl_.features_ = reinterpret_cast<::google::protobuf::FeatureSet*>(p);
   }
   return _impl_.features_;
@@ -16884,7 +16884,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000001u;
   if (_impl_.features_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FeatureSet>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FeatureSet>(GetArena());
     _impl_.features_ = reinterpret_cast<::google::protobuf::FeatureSet*>(p);
   }
   return _impl_.features_;
@@ -17033,7 +17033,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000001u;
   if (_impl_.features_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FeatureSet>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FeatureSet>(GetArena());
     _impl_.features_ = reinterpret_cast<::google::protobuf::FeatureSet*>(p);
   }
   return _impl_.features_;
@@ -17266,7 +17266,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000001u;
   if (_impl_.features_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FeatureSet>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FeatureSet>(GetArena());
     _impl_.features_ = reinterpret_cast<::google::protobuf::FeatureSet*>(p);
   }
   return _impl_.features_;
@@ -17443,7 +17443,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000001u;
   if (_impl_.features_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FeatureSet>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FeatureSet>(GetArena());
     _impl_.features_ = reinterpret_cast<::google::protobuf::FeatureSet*>(p);
   }
   return _impl_.features_;
@@ -17620,7 +17620,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000001u;
   if (_impl_.features_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FeatureSet>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FeatureSet>(GetArena());
     _impl_.features_ = reinterpret_cast<::google::protobuf::FeatureSet*>(p);
   }
   return _impl_.features_;
@@ -17854,7 +17854,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000001u;
   if (_impl_.features_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FeatureSet>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FeatureSet>(GetArena());
     _impl_.features_ = reinterpret_cast<::google::protobuf::FeatureSet*>(p);
   }
   return _impl_.features_;
@@ -18663,7 +18663,7 @@
   PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
   _impl_._has_bits_[0] |= 0x00000001u;
   if (_impl_.features_ == nullptr) {
-    auto* p = CreateMaybeMessage<::google::protobuf::FeatureSet>(GetArena());
+    auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FeatureSet>(GetArena());
     _impl_.features_ = reinterpret_cast<::google::protobuf::FeatureSet*>(p);
   }
   return _impl_.features_;
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index d6a473e..8b5e83c 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -651,11 +651,6 @@
                                             MessageLite* to) {
   to->CheckTypeAndMergeFrom(from);
 }
-template <>
-void GenericTypeHandler<std::string>::Merge(const std::string& from,
-                                            std::string* to) {
-  *to = from;
-}
 
 // Non-inline variants of std::string specializations for
 // various InternalMetadata routines.
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 74f6be8..58d44eb 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -505,13 +505,13 @@
   }
 
   template <typename T>
-  static T* CreateMaybeMessage(Arena* arena) {
-    return Arena::CreateMaybeMessage<T>(arena);
+  PROTOBUF_ALWAYS_INLINE static T* DefaultConstruct(Arena* arena) {
+    return static_cast<T*>(Arena::DefaultConstruct<T>(arena));
   }
 
   template <typename T>
-  static T* CreateMaybeMessage(Arena* arena, const T& from) {
-    return Arena::CreateMaybeMessage<T>(arena, from);
+  PROTOBUF_ALWAYS_INLINE static T* CopyConstruct(Arena* arena, const T& from) {
+    return static_cast<T*>(Arena::CopyConstruct<T>(arena, &from));
   }
 
   inline explicit MessageLite(Arena* arena) : _internal_metadata_(arena) {}
diff --git a/src/google/protobuf/repeated_ptr_field.cc b/src/google/protobuf/repeated_ptr_field.cc
index 4ac05d6..2a98da2 100644
--- a/src/google/protobuf/repeated_ptr_field.cc
+++ b/src/google/protobuf/repeated_ptr_field.cc
@@ -219,8 +219,8 @@
     const RepeatedPtrFieldBase& from, CopyFn copy_fn) {
   ABSL_DCHECK_NE(&from, this);
   int new_size = current_size_ + from.current_size_;
-  auto dst = reinterpret_cast<MessageLite**>(InternalReserve(new_size));
-  auto src = reinterpret_cast<MessageLite const* const*>(from.elements());
+  void** dst = InternalReserve(new_size);
+  const void* const* src = from.elements();
   auto end = src + from.current_size_;
   if (PROTOBUF_PREDICT_FALSE(ClearedCount() > 0)) {
     int recycled = MergeIntoClearedMessages(from);
@@ -229,7 +229,7 @@
   }
   Arena* arena = GetArena();
   for (; src < end; ++src, ++dst) {
-    *dst = copy_fn(arena, **src);
+    *dst = copy_fn(arena, *src);
   }
   ExchangeCurrentSize(new_size);
   if (new_size > allocated_size()) {
@@ -270,6 +270,10 @@
   }
 }
 
+void* NewStringElement(Arena* arena) {
+  return Arena::Create<std::string>(arena);
+}
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/repeated_ptr_field.h b/src/google/protobuf/repeated_ptr_field.h
index 02661f6..11ddd15 100644
--- a/src/google/protobuf/repeated_ptr_field.h
+++ b/src/google/protobuf/repeated_ptr_field.h
@@ -72,11 +72,6 @@
 
 namespace internal {
 
-template <typename Element>
-inline void* NewT(Arena* a) {
-  return GenericTypeHandler<Element>::New(a);
-}
-
 // Swaps two non-overlapping blocks of memory of size `N`
 template <size_t N>
 inline void memswap(char* PROTOBUF_RESTRICT a, char* PROTOBUF_RESTRICT b) {
@@ -229,7 +224,7 @@
 
   template <typename Handler>
   Value<Handler>* Add() {
-    return cast<Handler>(AddOutOfLineHelper(NewT<Value<Handler>>));
+    return cast<Handler>(AddOutOfLineHelper(Handler::GetNewFunc()));
   }
 
   template <
@@ -304,17 +299,11 @@
     }
   }
 
-  // Message creating functor: used in MergeFrom<T>()
-  template <typename T>
-  static MessageLite* CopyMessage(Arena* arena, const MessageLite& src) {
-    return Arena::CreateMaybeMessage<T>(arena, static_cast<const T&>(src));
-  }
-
   // Appends all message values from `from` to this instance.
   template <typename T>
   void MergeFrom(const RepeatedPtrFieldBase& from) {
     static_assert(std::is_base_of<MessageLite, T>::value, "");
-    MergeFromConcreteMessage(from, CopyMessage<T>);
+    MergeFromConcreteMessage(from, Arena::CopyConstruct<T>);
   }
 
   inline void InternalSwap(RepeatedPtrFieldBase* PROTOBUF_RESTRICT rhs) {
@@ -693,7 +682,7 @@
   // This follows the `Arena::CreateMaybeMessage` signature so that the compiler
   // can have the inlined call into the out of line copy function(s) simply pass
   // the address of `Arena::CreateMaybeMessage` 'as is'.
-  using CopyFn = MessageLite* (*)(Arena*, const MessageLite&);
+  using CopyFn = void* (*)(Arena*, const void*);
 
   struct Rep {
     int allocated_size;
@@ -891,8 +880,10 @@
   typedef GenericType Type;
   using Movable = IsMovable<GenericType>;
 
+  static constexpr auto GetNewFunc() { return Arena::DefaultConstruct<Type>; }
+
   static inline GenericType* New(Arena* arena) {
-    return Arena::CreateMaybeMessage<Type>(arena);
+    return static_cast<GenericType*>(Arena::DefaultConstruct<Type>(arena));
   }
   static inline GenericType* New(Arena* arena, GenericType&& value) {
     return Arena::Create<GenericType>(arena, std::move(value));
@@ -951,14 +942,6 @@
 PROTOBUF_EXPORT void GenericTypeHandler<MessageLite>::Merge(
     const MessageLite& from, MessageLite* to);
 
-template <>
-inline void GenericTypeHandler<std::string>::Clear(std::string* value) {
-  value->clear();
-}
-template <>
-void GenericTypeHandler<std::string>::Merge(const std::string& from,
-                                            std::string* to);
-
 // Message specialization bodies defined in message.cc. This split is necessary
 // to allow proto2-lite (which includes this header) to be independent of
 // Message.
@@ -968,11 +951,16 @@
 template <>
 PROTOBUF_EXPORT Arena* GenericTypeHandler<Message>::GetArena(Message* value);
 
-class StringTypeHandler {
+PROTOBUF_EXPORT void* NewStringElement(Arena* arena);
+
+template <>
+class GenericTypeHandler<std::string> {
  public:
   typedef std::string Type;
   using Movable = IsMovable<Type>;
 
+  static constexpr auto GetNewFunc() { return NewStringElement; }
+
   static PROTOBUF_NOINLINE std::string* New(Arena* arena) {
     return Arena::Create<std::string>(arena);
   }
@@ -1333,7 +1321,7 @@
   friend struct WeakRepeatedPtrField;
 
   // Note:  RepeatedPtrField SHOULD NOT be subclassed by users.
-  class TypeHandler;
+  using TypeHandler = internal::GenericTypeHandler<Element>;
 
   RepeatedPtrField(Arena* arena, const RepeatedPtrField& rhs);
 
@@ -1355,14 +1343,6 @@
 // -------------------------------------------------------------------
 
 template <typename Element>
-class RepeatedPtrField<Element>::TypeHandler
-    : public internal::GenericTypeHandler<Element> {};
-
-template <>
-class RepeatedPtrField<std::string>::TypeHandler
-    : public internal::StringTypeHandler {};
-
-template <typename Element>
 constexpr RepeatedPtrField<Element>::RepeatedPtrField()
     : RepeatedPtrFieldBase() {
   StaticValidityCheck();
@@ -1373,7 +1353,7 @@
     : RepeatedPtrFieldBase(arena) {
   // We can't have StaticValidityCheck here because that requires Element to be
   // a complete type, and in split repeated fields cases, we call
-  // CreateMaybeMessage<RepeatedPtrField<T>> for incomplete Ts.
+  // CreateMessage<RepeatedPtrField<T>> for incomplete Ts.
 }
 
 template <typename Element>