google-protobuf 3.11.0 → 3.12.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

File without changes
@@ -100,11 +100,11 @@ static VALUE table_key(Map* self, VALUE key,
100
100
  return key;
101
101
  }
102
102
 
103
- static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) {
103
+ static VALUE table_key_to_ruby(Map* self, upb_strview key) {
104
104
  switch (self->key_type) {
105
105
  case UPB_TYPE_BYTES:
106
106
  case UPB_TYPE_STRING: {
107
- VALUE ret = rb_str_new(buf, length);
107
+ VALUE ret = rb_str_new(key.data, key.size);
108
108
  rb_enc_associate(ret,
109
109
  (self->key_type == UPB_TYPE_BYTES) ?
110
110
  kRubyString8bitEncoding : kRubyStringUtf8Encoding);
@@ -116,7 +116,7 @@ static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) {
116
116
  case UPB_TYPE_INT64:
117
117
  case UPB_TYPE_UINT32:
118
118
  case UPB_TYPE_UINT64:
119
- return native_slot_get(self->key_type, Qnil, buf);
119
+ return native_slot_get(self->key_type, Qnil, key.data);
120
120
 
121
121
  default:
122
122
  assert(false);
@@ -289,9 +289,7 @@ VALUE Map_each(VALUE _self) {
289
289
  for (upb_strtable_begin(&it, &self->table);
290
290
  !upb_strtable_done(&it);
291
291
  upb_strtable_next(&it)) {
292
-
293
- VALUE key = table_key_to_ruby(
294
- self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
292
+ VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
295
293
 
296
294
  upb_value v = upb_strtable_iter_value(&it);
297
295
  void* mem = value_memory(&v);
@@ -319,9 +317,7 @@ VALUE Map_keys(VALUE _self) {
319
317
  for (upb_strtable_begin(&it, &self->table);
320
318
  !upb_strtable_done(&it);
321
319
  upb_strtable_next(&it)) {
322
-
323
- VALUE key = table_key_to_ruby(
324
- self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
320
+ VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
325
321
 
326
322
  rb_ary_push(ret, key);
327
323
  }
@@ -526,17 +522,14 @@ VALUE Map_dup(VALUE _self) {
526
522
  for (upb_strtable_begin(&it, &self->table);
527
523
  !upb_strtable_done(&it);
528
524
  upb_strtable_next(&it)) {
529
-
525
+ upb_strview k = upb_strtable_iter_key(&it);
530
526
  upb_value v = upb_strtable_iter_value(&it);
531
527
  void* mem = value_memory(&v);
532
528
  upb_value dup;
533
529
  void* dup_mem = value_memory(&dup);
534
530
  native_slot_dup(self->value_type, dup_mem, mem);
535
531
 
536
- if (!upb_strtable_insert2(&new_self->table,
537
- upb_strtable_iter_key(&it),
538
- upb_strtable_iter_keylength(&it),
539
- dup)) {
532
+ if (!upb_strtable_insert2(&new_self->table, k.data, k.size, dup)) {
540
533
  rb_raise(rb_eRuntimeError, "Error inserting value into new table");
541
534
  }
542
535
  }
@@ -554,7 +547,7 @@ VALUE Map_deep_copy(VALUE _self) {
554
547
  for (upb_strtable_begin(&it, &self->table);
555
548
  !upb_strtable_done(&it);
556
549
  upb_strtable_next(&it)) {
557
-
550
+ upb_strview k = upb_strtable_iter_key(&it);
558
551
  upb_value v = upb_strtable_iter_value(&it);
559
552
  void* mem = value_memory(&v);
560
553
  upb_value dup;
@@ -562,10 +555,7 @@ VALUE Map_deep_copy(VALUE _self) {
562
555
  native_slot_deep_copy(self->value_type, self->value_type_class, dup_mem,
563
556
  mem);
564
557
 
565
- if (!upb_strtable_insert2(&new_self->table,
566
- upb_strtable_iter_key(&it),
567
- upb_strtable_iter_keylength(&it),
568
- dup)) {
558
+ if (!upb_strtable_insert2(&new_self->table, k.data, k.size, dup)) {
569
559
  rb_raise(rb_eRuntimeError, "Error inserting value into new table");
570
560
  }
571
561
  }
@@ -618,16 +608,13 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
618
608
  for (upb_strtable_begin(&it, &self->table);
619
609
  !upb_strtable_done(&it);
620
610
  upb_strtable_next(&it)) {
621
-
611
+ upb_strview k = upb_strtable_iter_key(&it);
622
612
  upb_value v = upb_strtable_iter_value(&it);
623
613
  void* mem = value_memory(&v);
624
614
  upb_value other_v;
625
615
  void* other_mem = value_memory(&other_v);
626
616
 
627
- if (!upb_strtable_lookup2(&other->table,
628
- upb_strtable_iter_key(&it),
629
- upb_strtable_iter_keylength(&it),
630
- &other_v)) {
617
+ if (!upb_strtable_lookup2(&other->table, k.data, k.size, &other_v)) {
631
618
  // Not present in other map.
632
619
  return Qfalse;
633
620
  }
@@ -655,11 +642,9 @@ VALUE Map_hash(VALUE _self) {
655
642
  VALUE hash_sym = rb_intern("hash");
656
643
 
657
644
  upb_strtable_iter it;
658
- for (upb_strtable_begin(&it, &self->table);
659
- !upb_strtable_done(&it);
645
+ for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it);
660
646
  upb_strtable_next(&it)) {
661
- VALUE key = table_key_to_ruby(
662
- self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
647
+ VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
663
648
 
664
649
  upb_value v = upb_strtable_iter_value(&it);
665
650
  void* mem = value_memory(&v);
@@ -687,8 +672,7 @@ VALUE Map_to_h(VALUE _self) {
687
672
  for (upb_strtable_begin(&it, &self->table);
688
673
  !upb_strtable_done(&it);
689
674
  upb_strtable_next(&it)) {
690
- VALUE key = table_key_to_ruby(
691
- self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
675
+ VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
692
676
  upb_value v = upb_strtable_iter_value(&it);
693
677
  void* mem = value_memory(&v);
694
678
  VALUE value = native_slot_get(self->value_type,
@@ -720,11 +704,9 @@ VALUE Map_inspect(VALUE _self) {
720
704
  VALUE inspect_sym = rb_intern("inspect");
721
705
 
722
706
  upb_strtable_iter it;
723
- for (upb_strtable_begin(&it, &self->table);
724
- !upb_strtable_done(&it);
707
+ for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it);
725
708
  upb_strtable_next(&it)) {
726
- VALUE key = table_key_to_ruby(
727
- self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
709
+ VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
728
710
 
729
711
  upb_value v = upb_strtable_iter_value(&it);
730
712
  void* mem = value_memory(&v);
@@ -785,20 +767,15 @@ VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
785
767
  for (upb_strtable_begin(&it, &other->table);
786
768
  !upb_strtable_done(&it);
787
769
  upb_strtable_next(&it)) {
770
+ upb_strview k = upb_strtable_iter_key(&it);
788
771
 
789
772
  // Replace any existing value by issuing a 'remove' operation first.
790
773
  upb_value v;
791
774
  upb_value oldv;
792
- upb_strtable_remove2(&self->table,
793
- upb_strtable_iter_key(&it),
794
- upb_strtable_iter_keylength(&it),
795
- &oldv);
775
+ upb_strtable_remove2(&self->table, k.data, k.size, &oldv);
796
776
 
797
777
  v = upb_strtable_iter_value(&it);
798
- upb_strtable_insert2(&self->table,
799
- upb_strtable_iter_key(&it),
800
- upb_strtable_iter_keylength(&it),
801
- v);
778
+ upb_strtable_insert2(&self->table, k.data, k.size, v);
802
779
  }
803
780
  } else {
804
781
  rb_raise(rb_eArgError, "Unknown type merging into Map");
@@ -822,10 +799,7 @@ bool Map_done(Map_iter* iter) {
822
799
  }
823
800
 
824
801
  VALUE Map_iter_key(Map_iter* iter) {
825
- return table_key_to_ruby(
826
- iter->self,
827
- upb_strtable_iter_key(&iter->it),
828
- upb_strtable_iter_keylength(&iter->it));
802
+ return table_key_to_ruby(iter->self, upb_strtable_iter_key(&iter->it));
829
803
  }
830
804
 
831
805
  VALUE Map_iter_value(Map_iter* iter) {
@@ -242,9 +242,14 @@ static int extract_method_call(VALUE method_name, MessageHeader* self,
242
242
  // Method calls like 'has_foo?' are not allowed if field "foo" does not have
243
243
  // a hasbit (e.g. repeated fields or non-message type fields for proto3
244
244
  // syntax).
245
- if (accessor_type == METHOD_PRESENCE && test_f != NULL &&
246
- !upb_fielddef_haspresence(test_f)) {
247
- return METHOD_UNKNOWN;
245
+ if (accessor_type == METHOD_PRESENCE && test_f != NULL) {
246
+ if (!upb_fielddef_haspresence(test_f)) return METHOD_UNKNOWN;
247
+
248
+ // TODO(haberman): remove this case, allow for proto3 oneofs.
249
+ if (upb_fielddef_realcontainingoneof(test_f) &&
250
+ upb_filedef_syntax(upb_fielddef_file(test_f)) == UPB_SYNTAX_PROTO3) {
251
+ return METHOD_UNKNOWN;
252
+ }
248
253
  }
249
254
 
250
255
  *o = test_o;
@@ -605,11 +610,17 @@ VALUE Message_inspect(VALUE _self) {
605
610
  */
606
611
  VALUE Message_to_h(VALUE _self) {
607
612
  MessageHeader* self;
608
- VALUE hash;
613
+ VALUE hash = rb_hash_new();
609
614
  upb_msg_field_iter it;
615
+ bool is_proto2;
610
616
  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
611
617
 
612
- hash = rb_hash_new();
618
+ // We currently have a few behaviors that are specific to proto2.
619
+ // This is unfortunate, we should key behaviors off field attributes (like
620
+ // whether a field has presence), not proto2 vs. proto3. We should see if we
621
+ // can change this without breaking users.
622
+ is_proto2 =
623
+ upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2;
613
624
 
614
625
  for (upb_msg_field_begin(&it, self->descriptor->msgdef);
615
626
  !upb_msg_field_done(&it);
@@ -618,10 +629,9 @@ VALUE Message_to_h(VALUE _self) {
618
629
  VALUE msg_value;
619
630
  VALUE msg_key;
620
631
 
621
- // For proto2, do not include fields which are not set.
622
- if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
623
- field_contains_hasbit(self->descriptor->layout, field) &&
624
- !layout_has(self->descriptor->layout, Message_data(self), field)) {
632
+ // Do not include fields that are not present (oneof or optional fields).
633
+ if (is_proto2 && upb_fielddef_haspresence(field) &&
634
+ !layout_has(self->descriptor->layout, Message_data(self), field)) {
625
635
  continue;
626
636
  }
627
637
 
@@ -631,8 +641,7 @@ VALUE Message_to_h(VALUE _self) {
631
641
  msg_value = Map_to_h(msg_value);
632
642
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
633
643
  msg_value = RepeatedField_to_ary(msg_value);
634
- if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
635
- RARRAY_LEN(msg_value) == 0) {
644
+ if (is_proto2 && RARRAY_LEN(msg_value) == 0) {
636
645
  continue;
637
646
  }
638
647
 
@@ -285,6 +285,7 @@ VALUE MessageBuilderContext_initialize(VALUE _self,
285
285
  VALUE _file_builder,
286
286
  VALUE name);
287
287
  VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
288
+ VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv, VALUE _self);
288
289
  VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self);
289
290
  VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self);
290
291
  VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self);
@@ -496,11 +496,14 @@ void create_layout(Descriptor* desc) {
496
496
  const upb_msgdef *msgdef = desc->msgdef;
497
497
  MessageLayout* layout = ALLOC(MessageLayout);
498
498
  int nfields = upb_msgdef_numfields(msgdef);
499
- int noneofs = upb_msgdef_numoneofs(msgdef);
499
+ int noneofs = upb_msgdef_numrealoneofs(msgdef);
500
500
  upb_msg_field_iter it;
501
501
  upb_msg_oneof_iter oit;
502
502
  size_t off = 0;
503
503
  size_t hasbit = 0;
504
+ int i;
505
+
506
+ (void)i;
504
507
 
505
508
  layout->empty_template = NULL;
506
509
  layout->desc = desc;
@@ -513,11 +516,22 @@ void create_layout(Descriptor* desc) {
513
516
  layout->oneofs = ALLOC_N(MessageOneof, noneofs);
514
517
  }
515
518
 
519
+ #ifndef NDEBUG
520
+ for (i = 0; i < nfields; i++) {
521
+ layout->fields[i].offset = -1;
522
+ }
523
+
524
+ for (i = 0; i < noneofs; i++) {
525
+ layout->oneofs[i].offset = -1;
526
+ }
527
+ #endif
528
+
516
529
  for (upb_msg_field_begin(&it, msgdef);
517
530
  !upb_msg_field_done(&it);
518
531
  upb_msg_field_next(&it)) {
519
532
  const upb_fielddef* field = upb_msg_iter_field(&it);
520
- if (upb_fielddef_haspresence(field)) {
533
+ if (upb_fielddef_haspresence(field) &&
534
+ !upb_fielddef_realcontainingoneof(field)) {
521
535
  layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
522
536
  } else {
523
537
  layout->fields[upb_fielddef_index(field)].hasbit =
@@ -540,7 +554,7 @@ void create_layout(Descriptor* desc) {
540
554
  !upb_msg_field_done(&it);
541
555
  upb_msg_field_next(&it)) {
542
556
  const upb_fielddef* field = upb_msg_iter_field(&it);
543
- if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) ||
557
+ if (upb_fielddef_realcontainingoneof(field) || !upb_fielddef_isseq(field) ||
544
558
  upb_fielddef_ismap(field)) {
545
559
  continue;
546
560
  }
@@ -555,7 +569,7 @@ void create_layout(Descriptor* desc) {
555
569
  !upb_msg_field_done(&it);
556
570
  upb_msg_field_next(&it)) {
557
571
  const upb_fielddef* field = upb_msg_iter_field(&it);
558
- if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) ||
572
+ if (upb_fielddef_realcontainingoneof(field) || !upb_fielddef_isseq(field) ||
559
573
  !upb_fielddef_ismap(field)) {
560
574
  continue;
561
575
  }
@@ -572,7 +586,7 @@ void create_layout(Descriptor* desc) {
572
586
  !upb_msg_field_done(&it);
573
587
  upb_msg_field_next(&it)) {
574
588
  const upb_fielddef* field = upb_msg_iter_field(&it);
575
- if (upb_fielddef_containingoneof(field) || !is_value_field(field) ||
589
+ if (upb_fielddef_realcontainingoneof(field) || !is_value_field(field) ||
576
590
  upb_fielddef_isseq(field)) {
577
591
  continue;
578
592
  }
@@ -589,7 +603,7 @@ void create_layout(Descriptor* desc) {
589
603
  const upb_fielddef* field = upb_msg_iter_field(&it);
590
604
  size_t field_size;
591
605
 
592
- if (upb_fielddef_containingoneof(field) || is_value_field(field)) {
606
+ if (upb_fielddef_realcontainingoneof(field) || is_value_field(field)) {
593
607
  continue;
594
608
  }
595
609
 
@@ -624,6 +638,10 @@ void create_layout(Descriptor* desc) {
624
638
  // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
625
639
  // all fields.
626
640
  size_t field_size = NATIVE_SLOT_MAX_SIZE;
641
+
642
+ if (upb_oneofdef_issynthetic(oneof)) continue;
643
+ assert(upb_oneofdef_index(oneof) < noneofs);
644
+
627
645
  // Align the offset.
628
646
  off = align_up_to(off, field_size);
629
647
  // Assign all fields in the oneof this same offset.
@@ -643,6 +661,8 @@ void create_layout(Descriptor* desc) {
643
661
  upb_msg_oneof_next(&oit)) {
644
662
  const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
645
663
  size_t field_size = sizeof(uint32_t);
664
+ if (upb_oneofdef_issynthetic(oneof)) continue;
665
+ assert(upb_oneofdef_index(oneof) < noneofs);
646
666
  // Align the offset.
647
667
  off = (off + field_size - 1) & ~(field_size - 1);
648
668
  layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off;
@@ -652,6 +672,16 @@ void create_layout(Descriptor* desc) {
652
672
  layout->size = off;
653
673
  layout->msgdef = msgdef;
654
674
 
675
+ #ifndef NDEBUG
676
+ for (i = 0; i < nfields; i++) {
677
+ assert(layout->fields[i].offset != -1);
678
+ }
679
+
680
+ for (i = 0; i < noneofs; i++) {
681
+ assert(layout->oneofs[i].offset != -1);
682
+ }
683
+ #endif
684
+
655
685
  // Create the empty message template.
656
686
  layout->empty_template = ALLOC_N(char, layout->size);
657
687
  memset(layout->empty_template, 0, layout->size);
@@ -725,10 +755,7 @@ static bool slot_is_hasbit_set(MessageLayout* layout,
725
755
  const void* storage,
726
756
  const upb_fielddef* field) {
727
757
  size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
728
- if (hasbit == MESSAGE_FIELD_NO_HASBIT) {
729
- return false;
730
- }
731
-
758
+ assert(field_contains_hasbit(layout, field));
732
759
  return DEREF_OFFSET(
733
760
  (uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8));
734
761
  }
@@ -736,15 +763,21 @@ static bool slot_is_hasbit_set(MessageLayout* layout,
736
763
  VALUE layout_has(MessageLayout* layout,
737
764
  const void* storage,
738
765
  const upb_fielddef* field) {
739
- assert(field_contains_hasbit(layout, field));
740
- return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse;
766
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
767
+ assert(upb_fielddef_haspresence(field));
768
+ if (oneof) {
769
+ uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
770
+ return oneof_case == upb_fielddef_number(field) ? Qtrue : Qfalse;
771
+ } else {
772
+ return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse;
773
+ }
741
774
  }
742
775
 
743
776
  void layout_clear(MessageLayout* layout,
744
777
  const void* storage,
745
778
  const upb_fielddef* field) {
746
779
  void* memory = slot_memory(layout, storage, field);
747
- const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
780
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
748
781
 
749
782
  if (field_contains_hasbit(layout, field)) {
750
783
  slot_clear_hasbit(layout, storage, field);
@@ -837,7 +870,7 @@ VALUE layout_get(MessageLayout* layout,
837
870
  const void* storage,
838
871
  const upb_fielddef* field) {
839
872
  void* memory = slot_memory(layout, storage, field);
840
- const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
873
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
841
874
  bool field_set;
842
875
  if (field_contains_hasbit(layout, field)) {
843
876
  field_set = slot_is_hasbit_set(layout, storage, field);
@@ -910,7 +943,7 @@ void layout_set(MessageLayout* layout,
910
943
  const upb_fielddef* field,
911
944
  VALUE val) {
912
945
  void* memory = slot_memory(layout, storage, field);
913
- const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
946
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
914
947
 
915
948
  if (oneof) {
916
949
  uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
@@ -953,7 +986,16 @@ void layout_set(MessageLayout* layout,
953
986
 
954
987
  if (layout->fields[upb_fielddef_index(field)].hasbit !=
955
988
  MESSAGE_FIELD_NO_HASBIT) {
956
- slot_set_hasbit(layout, storage, field);
989
+ if (val == Qnil) {
990
+ // No other field type has a hasbit and allows nil assignment.
991
+ if (upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
992
+ fprintf(stderr, "field: %s\n", upb_fielddef_fullname(field));
993
+ }
994
+ assert(upb_fielddef_type(field) == UPB_TYPE_MESSAGE);
995
+ slot_clear_hasbit(layout, storage, field);
996
+ } else {
997
+ slot_set_hasbit(layout, storage, field);
998
+ }
957
999
  }
958
1000
  }
959
1001
 
@@ -972,7 +1014,7 @@ void layout_init(MessageLayout* layout, void* storage) {
972
1014
 
973
1015
  void layout_mark(MessageLayout* layout, void* storage) {
974
1016
  VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
975
- int noneofs = upb_msgdef_numoneofs(layout->msgdef);
1017
+ int noneofs = upb_msgdef_numrealoneofs(layout->msgdef);
976
1018
  int i;
977
1019
 
978
1020
  for (i = 0; i < layout->value_count; i++) {
@@ -994,7 +1036,7 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
994
1036
  !upb_msg_field_done(&it);
995
1037
  upb_msg_field_next(&it)) {
996
1038
  const upb_fielddef* field = upb_msg_iter_field(&it);
997
- const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
1039
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
998
1040
 
999
1041
  void* to_memory = slot_memory(layout, to, field);
1000
1042
  void* from_memory = slot_memory(layout, from, field);
@@ -1028,7 +1070,7 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
1028
1070
  !upb_msg_field_done(&it);
1029
1071
  upb_msg_field_next(&it)) {
1030
1072
  const upb_fielddef* field = upb_msg_iter_field(&it);
1031
- const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
1073
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
1032
1074
 
1033
1075
  void* to_memory = slot_memory(layout, to, field);
1034
1076
  void* from_memory = slot_memory(layout, from, field);
@@ -1068,7 +1110,7 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
1068
1110
  !upb_msg_field_done(&it);
1069
1111
  upb_msg_field_next(&it)) {
1070
1112
  const upb_fielddef* field = upb_msg_iter_field(&it);
1071
- const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
1113
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
1072
1114
 
1073
1115
  void* msg1_memory = slot_memory(layout, msg1, field);
1074
1116
  void* msg2_memory = slot_memory(layout, msg2, field);
@@ -1095,9 +1137,16 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
1095
1137
  return Qfalse;
1096
1138
  }
1097
1139
  } else {
1098
- if (slot_is_hasbit_set(layout, msg1, field) !=
1099
- slot_is_hasbit_set(layout, msg2, field) ||
1100
- !native_slot_eq(upb_fielddef_type(field),
1140
+ if (field_contains_hasbit(layout, field) &&
1141
+ slot_is_hasbit_set(layout, msg1, field) !=
1142
+ slot_is_hasbit_set(layout, msg2, field)) {
1143
+ // TODO(haberman): I don't think we should actually care about hasbits
1144
+ // here: an unset default should be able to equal a set default. But we
1145
+ // can address this later (will also have to make sure defaults are
1146
+ // being properly set when hasbit is clear).
1147
+ return Qfalse;
1148
+ }
1149
+ if (!native_slot_eq(upb_fielddef_type(field),
1101
1150
  field_type_class(layout, field), msg1_memory,
1102
1151
  msg2_memory)) {
1103
1152
  return Qfalse;