google-protobuf 3.6.1-x64-mingw32 → 3.7.0.rc.2-x64-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

@@ -38,6 +38,8 @@
38
38
  // Ruby <-> native slot management.
39
39
  // -----------------------------------------------------------------------------
40
40
 
41
+ #define CHARPTR_AT(msg, ofs) ((char*)msg + ofs)
42
+ #define DEREF_OFFSET(msg, ofs, type) *(type*)CHARPTR_AT(msg, ofs)
41
43
  #define DEREF(memory, type) *(type*)(memory)
42
44
 
43
45
  size_t native_slot_size(upb_fieldtype_t type) {
@@ -57,37 +59,6 @@ size_t native_slot_size(upb_fieldtype_t type) {
57
59
  }
58
60
  }
59
61
 
60
- static VALUE value_from_default(const upb_fielddef *field) {
61
- switch (upb_fielddef_type(field)) {
62
- case UPB_TYPE_FLOAT: return DBL2NUM(upb_fielddef_defaultfloat(field));
63
- case UPB_TYPE_DOUBLE: return DBL2NUM(upb_fielddef_defaultdouble(field));
64
- case UPB_TYPE_BOOL:
65
- return upb_fielddef_defaultbool(field) ? Qtrue : Qfalse;
66
- case UPB_TYPE_MESSAGE: return Qnil;
67
- case UPB_TYPE_ENUM: {
68
- const upb_enumdef *enumdef = upb_fielddef_enumsubdef(field);
69
- int32_t num = upb_fielddef_defaultint32(field);
70
- const char *label = upb_enumdef_iton(enumdef, num);
71
- if (label) {
72
- return ID2SYM(rb_intern(label));
73
- } else {
74
- return INT2NUM(num);
75
- }
76
- }
77
- case UPB_TYPE_INT32: return INT2NUM(upb_fielddef_defaultint32(field));
78
- case UPB_TYPE_INT64: return LL2NUM(upb_fielddef_defaultint64(field));;
79
- case UPB_TYPE_UINT32: return UINT2NUM(upb_fielddef_defaultuint32(field));
80
- case UPB_TYPE_UINT64: return ULL2NUM(upb_fielddef_defaultuint64(field));
81
- case UPB_TYPE_STRING:
82
- case UPB_TYPE_BYTES: {
83
- size_t size;
84
- const char *str = upb_fielddef_defaultstr(field, &size);
85
- return rb_str_new(str, size);
86
- }
87
- default: return Qnil;
88
- }
89
- }
90
-
91
62
  static bool is_ruby_num(VALUE value) {
92
63
  return (TYPE(value) == T_FLOAT ||
93
64
  TYPE(value) == T_FIXNUM ||
@@ -96,7 +67,7 @@ static bool is_ruby_num(VALUE value) {
96
67
 
97
68
  void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
98
69
  if (!is_ruby_num(val)) {
99
- rb_raise(rb_eTypeError, "Expected number type for integral field.");
70
+ rb_raise(cTypeError, "Expected number type for integral field.");
100
71
  }
101
72
 
102
73
  // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
@@ -153,13 +124,13 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
153
124
  switch (type) {
154
125
  case UPB_TYPE_FLOAT:
155
126
  if (!is_ruby_num(value)) {
156
- rb_raise(rb_eTypeError, "Expected number type for float field.");
127
+ rb_raise(cTypeError, "Expected number type for float field.");
157
128
  }
158
129
  DEREF(memory, float) = NUM2DBL(value);
159
130
  break;
160
131
  case UPB_TYPE_DOUBLE:
161
132
  if (!is_ruby_num(value)) {
162
- rb_raise(rb_eTypeError, "Expected number type for double field.");
133
+ rb_raise(cTypeError, "Expected number type for double field.");
163
134
  }
164
135
  DEREF(memory, double) = NUM2DBL(value);
165
136
  break;
@@ -170,7 +141,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
170
141
  } else if (value == Qfalse) {
171
142
  val = 0;
172
143
  } else {
173
- rb_raise(rb_eTypeError, "Invalid argument for boolean field.");
144
+ rb_raise(cTypeError, "Invalid argument for boolean field.");
174
145
  }
175
146
  DEREF(memory, int8_t) = val;
176
147
  break;
@@ -179,7 +150,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
179
150
  if (CLASS_OF(value) == rb_cSymbol) {
180
151
  value = rb_funcall(value, rb_intern("to_s"), 0);
181
152
  } else if (CLASS_OF(value) != rb_cString) {
182
- rb_raise(rb_eTypeError, "Invalid argument for string field.");
153
+ rb_raise(cTypeError, "Invalid argument for string field.");
183
154
  }
184
155
 
185
156
  DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
@@ -187,7 +158,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
187
158
 
188
159
  case UPB_TYPE_BYTES: {
189
160
  if (CLASS_OF(value) != rb_cString) {
190
- rb_raise(rb_eTypeError, "Invalid argument for string field.");
161
+ rb_raise(cTypeError, "Invalid argument for string field.");
191
162
  }
192
163
 
193
164
  DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
@@ -197,7 +168,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
197
168
  if (CLASS_OF(value) == CLASS_OF(Qnil)) {
198
169
  value = Qnil;
199
170
  } else if (CLASS_OF(value) != type_class) {
200
- rb_raise(rb_eTypeError,
171
+ rb_raise(cTypeError,
201
172
  "Invalid type %s to assign to submessage field.",
202
173
  rb_class2name(CLASS_OF(value)));
203
174
  }
@@ -209,7 +180,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
209
180
  if (TYPE(value) == T_STRING) {
210
181
  value = rb_funcall(value, rb_intern("to_sym"), 0);
211
182
  } else if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
212
- rb_raise(rb_eTypeError,
183
+ rb_raise(cTypeError,
213
184
  "Expected number or symbol type for enum field.");
214
185
  }
215
186
  if (TYPE(value) == T_SYMBOL) {
@@ -404,7 +375,12 @@ const upb_msgdef *map_entry_msgdef(const upb_fielddef* field) {
404
375
  }
405
376
 
406
377
  bool is_map_field(const upb_fielddef *field) {
407
- return tryget_map_entry_msgdef(field) != NULL;
378
+ const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
379
+ if (subdef == NULL) return false;
380
+
381
+ // Map fields are a proto3 feature.
382
+ // If we're using proto2 syntax we need to fallback to the repeated field.
383
+ return upb_msgdef_syntax(subdef) == UPB_SYNTAX_PROTO3;
408
384
  }
409
385
 
410
386
  const upb_fielddef* map_field_key(const upb_fielddef* field) {
@@ -433,6 +409,12 @@ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
433
409
  // Memory layout management.
434
410
  // -----------------------------------------------------------------------------
435
411
 
412
+ bool field_contains_hasbit(MessageLayout* layout,
413
+ const upb_fielddef* field) {
414
+ return layout->fields[upb_fielddef_index(field)].hasbit !=
415
+ MESSAGE_FIELD_NO_HASBIT;
416
+ }
417
+
436
418
  static size_t align_up_to(size_t offset, size_t granularity) {
437
419
  // Granularity must be a power of two.
438
420
  return (offset + granularity - 1) & ~(granularity - 1);
@@ -447,6 +429,23 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
447
429
 
448
430
  layout->fields = ALLOC_N(MessageField, nfields);
449
431
 
432
+ size_t hasbit = 0;
433
+ for (upb_msg_field_begin(&it, msgdef);
434
+ !upb_msg_field_done(&it);
435
+ upb_msg_field_next(&it)) {
436
+ const upb_fielddef* field = upb_msg_iter_field(&it);
437
+ if (upb_fielddef_haspresence(field)) {
438
+ layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
439
+ } else {
440
+ layout->fields[upb_fielddef_index(field)].hasbit =
441
+ MESSAGE_FIELD_NO_HASBIT;
442
+ }
443
+ }
444
+
445
+ if (hasbit != 0) {
446
+ off += (hasbit + 8 - 1) / 8;
447
+ }
448
+
450
449
  for (upb_msg_field_begin(&it, msgdef);
451
450
  !upb_msg_field_done(&it);
452
451
  upb_msg_field_next(&it)) {
@@ -569,6 +568,136 @@ static uint32_t* slot_oneof_case(MessageLayout* layout,
569
568
  layout->fields[upb_fielddef_index(field)].case_offset);
570
569
  }
571
570
 
571
+ static void slot_set_hasbit(MessageLayout* layout,
572
+ const void* storage,
573
+ const upb_fielddef* field) {
574
+ size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
575
+ assert(hasbit != MESSAGE_FIELD_NO_HASBIT);
576
+
577
+ ((uint8_t*)storage)[hasbit / 8] |= 1 << (hasbit % 8);
578
+ }
579
+
580
+ static void slot_clear_hasbit(MessageLayout* layout,
581
+ const void* storage,
582
+ const upb_fielddef* field) {
583
+ size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
584
+ assert(hasbit != MESSAGE_FIELD_NO_HASBIT);
585
+ ((uint8_t*)storage)[hasbit / 8] &= ~(1 << (hasbit % 8));
586
+ }
587
+
588
+ static bool slot_is_hasbit_set(MessageLayout* layout,
589
+ const void* storage,
590
+ const upb_fielddef* field) {
591
+ size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
592
+ if (hasbit == MESSAGE_FIELD_NO_HASBIT) {
593
+ return false;
594
+ }
595
+
596
+ return DEREF_OFFSET(
597
+ (uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8));
598
+ }
599
+
600
+ VALUE layout_has(MessageLayout* layout,
601
+ const void* storage,
602
+ const upb_fielddef* field) {
603
+ assert(field_contains_hasbit(layout, field));
604
+ return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse;
605
+ }
606
+
607
+ void layout_clear(MessageLayout* layout,
608
+ const void* storage,
609
+ const upb_fielddef* field) {
610
+ void* memory = slot_memory(layout, storage, field);
611
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
612
+
613
+ if (field_contains_hasbit(layout, field)) {
614
+ slot_clear_hasbit(layout, storage, field);
615
+ }
616
+
617
+ if (upb_fielddef_containingoneof(field)) {
618
+ memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
619
+ *oneof_case = ONEOF_CASE_NONE;
620
+ } else if (is_map_field(field)) {
621
+ VALUE map = Qnil;
622
+
623
+ const upb_fielddef* key_field = map_field_key(field);
624
+ const upb_fielddef* value_field = map_field_value(field);
625
+ VALUE type_class = field_type_class(value_field);
626
+
627
+ if (type_class != Qnil) {
628
+ VALUE args[3] = {
629
+ fieldtype_to_ruby(upb_fielddef_type(key_field)),
630
+ fieldtype_to_ruby(upb_fielddef_type(value_field)),
631
+ type_class,
632
+ };
633
+ map = rb_class_new_instance(3, args, cMap);
634
+ } else {
635
+ VALUE args[2] = {
636
+ fieldtype_to_ruby(upb_fielddef_type(key_field)),
637
+ fieldtype_to_ruby(upb_fielddef_type(value_field)),
638
+ };
639
+ map = rb_class_new_instance(2, args, cMap);
640
+ }
641
+
642
+ DEREF(memory, VALUE) = map;
643
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
644
+ VALUE ary = Qnil;
645
+
646
+ VALUE type_class = field_type_class(field);
647
+
648
+ if (type_class != Qnil) {
649
+ VALUE args[2] = {
650
+ fieldtype_to_ruby(upb_fielddef_type(field)),
651
+ type_class,
652
+ };
653
+ ary = rb_class_new_instance(2, args, cRepeatedField);
654
+ } else {
655
+ VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
656
+ ary = rb_class_new_instance(1, args, cRepeatedField);
657
+ }
658
+
659
+ DEREF(memory, VALUE) = ary;
660
+ } else {
661
+ native_slot_set(upb_fielddef_type(field), field_type_class(field),
662
+ memory, layout_get_default(field));
663
+ }
664
+ }
665
+
666
+ VALUE layout_get_default(const upb_fielddef *field) {
667
+ switch (upb_fielddef_type(field)) {
668
+ case UPB_TYPE_FLOAT: return DBL2NUM(upb_fielddef_defaultfloat(field));
669
+ case UPB_TYPE_DOUBLE: return DBL2NUM(upb_fielddef_defaultdouble(field));
670
+ case UPB_TYPE_BOOL:
671
+ return upb_fielddef_defaultbool(field) ? Qtrue : Qfalse;
672
+ case UPB_TYPE_MESSAGE: return Qnil;
673
+ case UPB_TYPE_ENUM: {
674
+ const upb_enumdef *enumdef = upb_fielddef_enumsubdef(field);
675
+ int32_t num = upb_fielddef_defaultint32(field);
676
+ const char *label = upb_enumdef_iton(enumdef, num);
677
+ if (label) {
678
+ return ID2SYM(rb_intern(label));
679
+ } else {
680
+ return INT2NUM(num);
681
+ }
682
+ }
683
+ case UPB_TYPE_INT32: return INT2NUM(upb_fielddef_defaultint32(field));
684
+ case UPB_TYPE_INT64: return LL2NUM(upb_fielddef_defaultint64(field));;
685
+ case UPB_TYPE_UINT32: return UINT2NUM(upb_fielddef_defaultuint32(field));
686
+ case UPB_TYPE_UINT64: return ULL2NUM(upb_fielddef_defaultuint64(field));
687
+ case UPB_TYPE_STRING:
688
+ case UPB_TYPE_BYTES: {
689
+ size_t size;
690
+ const char *str = upb_fielddef_defaultstr(field, &size);
691
+ VALUE str_rb = rb_str_new(str, size);
692
+
693
+ rb_enc_associate(str_rb, (upb_fielddef_type(field) == UPB_TYPE_BYTES) ?
694
+ kRubyString8bitEncoding : kRubyStringUtf8Encoding);
695
+ rb_obj_freeze(str_rb);
696
+ return str_rb;
697
+ }
698
+ default: return Qnil;
699
+ }
700
+ }
572
701
 
573
702
  VALUE layout_get(MessageLayout* layout,
574
703
  const void* storage,
@@ -576,15 +705,24 @@ VALUE layout_get(MessageLayout* layout,
576
705
  void* memory = slot_memory(layout, storage, field);
577
706
  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
578
707
 
708
+ bool field_set;
709
+ if (field_contains_hasbit(layout, field)) {
710
+ field_set = slot_is_hasbit_set(layout, storage, field);
711
+ } else {
712
+ field_set = true;
713
+ }
714
+
579
715
  if (upb_fielddef_containingoneof(field)) {
580
716
  if (*oneof_case != upb_fielddef_number(field)) {
581
- return value_from_default(field);
717
+ return layout_get_default(field);
582
718
  }
583
719
  return native_slot_get(upb_fielddef_type(field),
584
720
  field_type_class(field),
585
721
  memory);
586
722
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
587
723
  return *((VALUE *)memory);
724
+ } else if (!field_set) {
725
+ return layout_get_default(field);
588
726
  } else {
589
727
  return native_slot_get(upb_fielddef_type(field),
590
728
  field_type_class(field),
@@ -598,18 +736,18 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
598
736
 
599
737
  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
600
738
  RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
601
- rb_raise(rb_eTypeError, "Expected repeated field array");
739
+ rb_raise(cTypeError, "Expected repeated field array");
602
740
  }
603
741
 
604
742
  self = ruby_to_RepeatedField(val);
605
743
  if (self->field_type != upb_fielddef_type(field)) {
606
- rb_raise(rb_eTypeError, "Repeated field array has wrong element type");
744
+ rb_raise(cTypeError, "Repeated field array has wrong element type");
607
745
  }
608
746
 
609
- if (self->field_type == UPB_TYPE_MESSAGE) {
747
+ if (self->field_type == UPB_TYPE_MESSAGE) {
610
748
  if (self->field_type_class !=
611
749
  Descriptor_msgclass(get_def_obj(upb_fielddef_subdef(field)))) {
612
- rb_raise(rb_eTypeError,
750
+ rb_raise(cTypeError,
613
751
  "Repeated field array has wrong message class");
614
752
  }
615
753
  }
@@ -618,7 +756,7 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
618
756
  if (self->field_type == UPB_TYPE_ENUM) {
619
757
  if (self->field_type_class !=
620
758
  EnumDescriptor_enummodule(get_def_obj(upb_fielddef_subdef(field)))) {
621
- rb_raise(rb_eTypeError,
759
+ rb_raise(cTypeError,
622
760
  "Repeated field array has wrong enum class");
623
761
  }
624
762
  }
@@ -631,21 +769,21 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
631
769
 
632
770
  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
633
771
  RTYPEDDATA_TYPE(val) != &Map_type) {
634
- rb_raise(rb_eTypeError, "Expected Map instance");
772
+ rb_raise(cTypeError, "Expected Map instance");
635
773
  }
636
774
 
637
775
  self = ruby_to_Map(val);
638
776
  if (self->key_type != upb_fielddef_type(key_field)) {
639
- rb_raise(rb_eTypeError, "Map key type does not match field's key type");
777
+ rb_raise(cTypeError, "Map key type does not match field's key type");
640
778
  }
641
779
  if (self->value_type != upb_fielddef_type(value_field)) {
642
- rb_raise(rb_eTypeError, "Map value type does not match field's value type");
780
+ rb_raise(cTypeError, "Map value type does not match field's value type");
643
781
  }
644
782
  if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE ||
645
783
  upb_fielddef_type(value_field) == UPB_TYPE_ENUM) {
646
784
  if (self->value_type_class !=
647
785
  get_def_obj(upb_fielddef_subdef(value_field))) {
648
- rb_raise(rb_eTypeError,
786
+ rb_raise(cTypeError,
649
787
  "Map value type has wrong message/enum class");
650
788
  }
651
789
  }
@@ -689,67 +827,24 @@ void layout_set(MessageLayout* layout,
689
827
  check_repeated_field_type(val, field);
690
828
  DEREF(memory, VALUE) = val;
691
829
  } else {
692
- native_slot_set(upb_fielddef_type(field), field_type_class(field),
693
- memory, val);
830
+ native_slot_set(upb_fielddef_type(field), field_type_class(field), memory,
831
+ val);
832
+ }
833
+
834
+ if (layout->fields[upb_fielddef_index(field)].hasbit !=
835
+ MESSAGE_FIELD_NO_HASBIT) {
836
+ slot_set_hasbit(layout, storage, field);
694
837
  }
695
838
  }
696
839
 
697
840
  void layout_init(MessageLayout* layout,
698
841
  void* storage) {
842
+
699
843
  upb_msg_field_iter it;
700
844
  for (upb_msg_field_begin(&it, layout->msgdef);
701
845
  !upb_msg_field_done(&it);
702
846
  upb_msg_field_next(&it)) {
703
- const upb_fielddef* field = upb_msg_iter_field(&it);
704
- void* memory = slot_memory(layout, storage, field);
705
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
706
-
707
- if (upb_fielddef_containingoneof(field)) {
708
- memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
709
- *oneof_case = ONEOF_CASE_NONE;
710
- } else if (is_map_field(field)) {
711
- VALUE map = Qnil;
712
-
713
- const upb_fielddef* key_field = map_field_key(field);
714
- const upb_fielddef* value_field = map_field_value(field);
715
- VALUE type_class = field_type_class(value_field);
716
-
717
- if (type_class != Qnil) {
718
- VALUE args[3] = {
719
- fieldtype_to_ruby(upb_fielddef_type(key_field)),
720
- fieldtype_to_ruby(upb_fielddef_type(value_field)),
721
- type_class,
722
- };
723
- map = rb_class_new_instance(3, args, cMap);
724
- } else {
725
- VALUE args[2] = {
726
- fieldtype_to_ruby(upb_fielddef_type(key_field)),
727
- fieldtype_to_ruby(upb_fielddef_type(value_field)),
728
- };
729
- map = rb_class_new_instance(2, args, cMap);
730
- }
731
-
732
- DEREF(memory, VALUE) = map;
733
- } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
734
- VALUE ary = Qnil;
735
-
736
- VALUE type_class = field_type_class(field);
737
-
738
- if (type_class != Qnil) {
739
- VALUE args[2] = {
740
- fieldtype_to_ruby(upb_fielddef_type(field)),
741
- type_class,
742
- };
743
- ary = rb_class_new_instance(2, args, cRepeatedField);
744
- } else {
745
- VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
746
- ary = rb_class_new_instance(1, args, cRepeatedField);
747
- }
748
-
749
- DEREF(memory, VALUE) = ary;
750
- } else {
751
- native_slot_init(upb_fielddef_type(field), memory);
752
- }
847
+ layout_clear(layout, storage, upb_msg_iter_field(&it));
753
848
  }
754
849
  }
755
850
 
@@ -796,6 +891,11 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
796
891
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
797
892
  DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
798
893
  } else {
894
+ if (field_contains_hasbit(layout, field)) {
895
+ if (!slot_is_hasbit_set(layout, from, field)) continue;
896
+ slot_set_hasbit(layout, to, field);
897
+ }
898
+
799
899
  native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
800
900
  }
801
901
  }
@@ -825,6 +925,11 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
825
925
  DEREF(to_memory, VALUE) =
826
926
  RepeatedField_deep_copy(DEREF(from_memory, VALUE));
827
927
  } else {
928
+ if (field_contains_hasbit(layout, field)) {
929
+ if (!slot_is_hasbit_set(layout, from, field)) continue;
930
+ slot_set_hasbit(layout, to, field);
931
+ }
932
+
828
933
  native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
829
934
  }
830
935
  }
@@ -861,8 +966,10 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
861
966
  return Qfalse;
862
967
  }
863
968
  } else {
864
- if (!native_slot_eq(upb_fielddef_type(field),
865
- msg1_memory, msg2_memory)) {
969
+ if (slot_is_hasbit_set(layout, msg1, field) !=
970
+ slot_is_hasbit_set(layout, msg2, field) ||
971
+ !native_slot_eq(upb_fielddef_type(field),
972
+ msg1_memory, msg2_memory)) {
866
973
  return Qfalse;
867
974
  }
868
975
  }