allow_alias equality semantics differ between generated Scala and Java code
awwsmm opened this issue · comments
allow_alias
allows two Protobuf enum variants to share the same value
, for example
enum People {
option allow_alias = true;
// ...
GeddyLee = 10;
NeilPeart = 11;
TheProfessor = 11; // an alias for NeilPeart
AlexLifeson = 12;
// ...
}
Above, NeilPeart
and TheProfessor
are equivalent with respect to their value
, which is 11
in both cases.
ScalaPB generates the following (abridged) Java code for this example
/**
* <code>TheProfessor = 11;</code>
*/
public static final People TheProfessor = NeilPeart;
The alias is the same object as the original object. Comparing them, we see that they are identically equal
// ScalaTest which passes
it should "be equal in Java" in {
toJavaValue(proto.People.NeilPeart) shouldEqual toJavaValue(proto.People.TheProfessor)
}
ScalaPB generates the following (abridged) Scala code for this example
@SerialVersionUID(0L)
case object NeilPeart extends People(11) with People.Recognized {
val index = 11
val name = "NeilPeart"
override def isNeilPeart: _root_.scala.Boolean = true
}
@SerialVersionUID(0L)
case object TheProfessor extends People(11) with People.Recognized {
val index = 12
val name = "TheProfessor"
override def isTheProfessor _root_.scala.Boolean = true
}
These two case object
s are different objects. For them to equal each other in Scala code, we must override equals
/ hashCode
(comparing them based on value
alone). This is currently not being done, and so we have different semantics for generated Scala aliases compared to generated Java aliases.
(THIS IS THE BUG)
The following test fails, though it is equivalent to the Java test above
// ScalaTest which fails
it should "be equal in Scala" in {
proto.People.NeilPeart shouldEqual proto.People.TheProfessor
}
Thanks for reporting! The java generated code actually creates a reference to the same enum, so following the example above in Scala, would generate:
@SerialVersionUID(0L)
case object NeilPeart extends People(11) with People.Recognized {
val index = 11
val name = "NeilPeart"
override def isNeilPeart: _root_.scala.Boolean = true
override def isTheProfessor: _root_.scala.Boolean = true // <-- note this change too
}
@transient val TheProfessor = NeilPeart