From 6c514f8d16320a346f01b32b3f1ec4714ed8aa89 Mon Sep 17 00:00:00 2001 From: Eric Salo Date: Mon, 6 Mar 2023 12:46:07 -0800 Subject: [PATCH] Automated rollback of commit 116cf4a41d42c1d8f0f31ecb950202ca051d6ec2. PiperOrigin-RevId: 514495606 --- src/google/protobuf/descriptor.cc | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 9827ac1376..efcd86e358 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -8417,7 +8417,18 @@ bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) { } bool HasHasbit(const FieldDescriptor* field) { - return field->has_presence() && !field->real_containing_oneof() && + // This predicate includes proto3 message fields only if they have "optional". + // Foo submsg1 = 1; // HasHasbit() == false + // optional Foo submsg2 = 2; // HasHasbit() == true + // This is slightly odd, as adding "optional" to a singular proto3 field does + // not change the semantics or API. However whenever any field in a message + // has a hasbit, it forces reflection to include hasbit offsets for *all* + // fields, even if almost all of them are set to -1 (no hasbit). So to avoid + // causing a sudden size regression for ~all proto3 messages, we give proto3 + // message fields a hasbit only if "optional" is present. If the user is + // explicitly writing "optional", it is likely they are writing it on + // primitive fields also. + return (field->has_optional_keyword() || field->is_required()) && !field->options().weak(); }