|
|
|
@ -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(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|