Skip to content

proto3 non-optional field presence effects message equality, hash code #691

@osa1

Description

@osa1

References for proto3 optional syntax:

Quoting the second reference above:

The no presence serialization discipline results in visible differences from the explicit presence tracking discipline, when the default value is set. For a singular field with numeric, enum, or string type:

  • No presence discipline:
    ...
    The default value may mean:
    • the field was explicitly set to its default value, which is valid in the application-specific domain of values;
    • the field was notionally "cleared" by setting its default; or
    • the field was never set.

In addition, it says

Without the optional label, proto3 APIs do not track presence for basic types (numeric, string, bytes, and enums), either

So in proto3, without optional, a field with default value cannot be distinguished from the non-presence of the same field. In all cases the value of the field is the default one, and presence of the field is not tracked.

With all this information, as a user, I would expect a message with default int32 value, and a message with the field non-present to be equal, and generate the same hash code, as the difference should not be observed. This currently does not hold:

// field tag is 9
var m1 = Msg1()..mergeFromBuffer([72, 0]);
var m2 = Msg1()..mergeFromBuffer([]);

print('hash codes equal = ${m1.hashCode == m2.hashCode}');
print('values equal = ${m1 == m2}');

Output:

hash codes equal = false
values equal = false

We also generate a hazzer for this field, and it works as if the field was optional. That's also a bug, but I think an separate one. For example, we could be generating hazzers and track presence, but without using the hazzer the messages could be identical (i.e. equal, with same hash code, all other API methods returning the same values).

b/134058565

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions