|  | @@ -517,7 +517,8 @@ void create_layout(Descriptor* desc) {
 | 
	
		
			
				|  |  |         !upb_msg_field_done(&it);
 | 
	
		
			
				|  |  |         upb_msg_field_next(&it)) {
 | 
	
		
			
				|  |  |      const upb_fielddef* field = upb_msg_iter_field(&it);
 | 
	
		
			
				|  |  | -    if (upb_fielddef_haspresence(field)) {
 | 
	
		
			
				|  |  | +    if (upb_fielddef_haspresence(field) &&
 | 
	
		
			
				|  |  | +        !upb_fielddef_containingoneof(field)) {
 | 
	
		
			
				|  |  |        layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  |        layout->fields[upb_fielddef_index(field)].hasbit =
 | 
	
	
		
			
				|  | @@ -724,11 +725,8 @@ static void slot_clear_hasbit(MessageLayout* layout,
 | 
	
		
			
				|  |  |  static bool slot_is_hasbit_set(MessageLayout* layout,
 | 
	
		
			
				|  |  |                              const void* storage,
 | 
	
		
			
				|  |  |                              const upb_fielddef* field) {
 | 
	
		
			
				|  |  | +  assert(field_contains_hasbit(layout, field));
 | 
	
		
			
				|  |  |    size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
 | 
	
		
			
				|  |  | -  if (hasbit == MESSAGE_FIELD_NO_HASBIT) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    return DEREF_OFFSET(
 | 
	
		
			
				|  |  |        (uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8));
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -736,8 +734,14 @@ static bool slot_is_hasbit_set(MessageLayout* layout,
 | 
	
		
			
				|  |  |  VALUE layout_has(MessageLayout* layout,
 | 
	
		
			
				|  |  |                   const void* storage,
 | 
	
		
			
				|  |  |                   const upb_fielddef* field) {
 | 
	
		
			
				|  |  | -  assert(field_contains_hasbit(layout, field));
 | 
	
		
			
				|  |  | -  return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse;
 | 
	
		
			
				|  |  | +  assert(upb_fielddef_haspresence(field));
 | 
	
		
			
				|  |  | +  const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
 | 
	
		
			
				|  |  | +  if (oneof) {
 | 
	
		
			
				|  |  | +    uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
 | 
	
		
			
				|  |  | +    return oneof_case == upb_fielddef_number(field);
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void layout_clear(MessageLayout* layout,
 | 
	
	
		
			
				|  | @@ -953,7 +957,16 @@ void layout_set(MessageLayout* layout,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (layout->fields[upb_fielddef_index(field)].hasbit !=
 | 
	
		
			
				|  |  |        MESSAGE_FIELD_NO_HASBIT) {
 | 
	
		
			
				|  |  | -    slot_set_hasbit(layout, storage, field);
 | 
	
		
			
				|  |  | +    if (val == Qnil) {
 | 
	
		
			
				|  |  | +      // No other field type has a hasbit and allows nil assignment.
 | 
	
		
			
				|  |  | +      if (upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
 | 
	
		
			
				|  |  | +        fprintf(stderr, "field: %s\n", upb_fielddef_fullname(field));
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      assert(upb_fielddef_type(field) == UPB_TYPE_MESSAGE);
 | 
	
		
			
				|  |  | +      slot_clear_hasbit(layout, storage, field);
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      slot_set_hasbit(layout, storage, field);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1095,9 +1108,16 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
 | 
	
		
			
				|  |  |          return Qfalse;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | -      if (slot_is_hasbit_set(layout, msg1, field) !=
 | 
	
		
			
				|  |  | -              slot_is_hasbit_set(layout, msg2, field) ||
 | 
	
		
			
				|  |  | -          !native_slot_eq(upb_fielddef_type(field),
 | 
	
		
			
				|  |  | +      if (field_contains_hasbit(layout, field) &&
 | 
	
		
			
				|  |  | +          slot_is_hasbit_set(layout, msg1, field) !=
 | 
	
		
			
				|  |  | +              slot_is_hasbit_set(layout, msg2, field)) {
 | 
	
		
			
				|  |  | +        // TODO(haberman): I don't think we should actually care about hasbits
 | 
	
		
			
				|  |  | +        // here: an unset default should be able to equal a set default. But we
 | 
	
		
			
				|  |  | +        // can address this later (will also have to make sure defaults are
 | 
	
		
			
				|  |  | +        // being properly set when hasbit is clear).
 | 
	
		
			
				|  |  | +        return Qfalse;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (!native_slot_eq(upb_fielddef_type(field),
 | 
	
		
			
				|  |  |                            field_type_class(layout, field), msg1_memory,
 | 
	
		
			
				|  |  |                            msg2_memory)) {
 | 
	
		
			
				|  |  |          return Qfalse;
 |