google/flatbuffers

Java enum name() function source compatibility issue

Opened this issue · 1 comments

Affected languages: Java
FlatBuffer versions: 24.3.25

When adding new enum constants to an existing FlatBuffers enum,
the generated Java code can change in ways that break backwards source compatibility.
This is surprising behaviour and is not documented anywhere.

In particular, the name method and the names static member in the generated Java class are only generated if the enum type is not too sparse. Adding new enum constants can increase the sparseness, causing name and names to no longer be generated. This can break backwards source compatibility with existing source code using name or names.

Either this behaviour should be documented, or (better) the name method should be generated unconditionally, and the names static member should be deprecated and replaced with a means of iterating over all the enum constants in an enum that can work when the enum is sparse.

The only place that I could find where this behaviour described at all is in the source code for the flatbuffer compiler,
specifically in src/idl_gen_java.cc, in the GenEnum function

// Generate a string table for enum values.
:

    void GenEnum(EnumDef &enum_def, std::string &code) const {
...
     // Generate a string table for enum values.
      // Problem is, if values are very sparse that could generate really big
      // tables. Ideally in that case we generate a map lookup instead, but for
      // the moment we simply don't output a table at all.
      auto range = enum_def.Distance();
      // Average distance between values above which we consider a table
      // "too sparse". Change at will.
      static const uint64_t kMaxSparseness = 5;
      if (range / static_cast<uint64_t>(enum_def.size()) < kMaxSparseness &&
          GenTypeBasic(DestinationType(enum_def.underlying_type, false)) !=
              "long") {

The same issue also applies to C++ and Kotlin.
For Kotlin, it applies to both the JVM and KMP backends.

See: