Value Class Equality

2021-05-31T00:00:00+00:00
Justin Brooks (justin@jzbrooks.com, https://jzbrooks.com/)

Value classes show a lot of promise for bringing value semantics to Kotlin classes. The feature is still young, but it isn’t hidden behind a compiler option anymore, so I’ll consider it fair game.

I guess I’ve been drinking a large glass of data class, so I was initially surprised to find reference semantics in comparison of value classes that wrap primitive arrays. Take the following code:

@JvmInline
value class Matrix(private val rowMajorData: IntArray)

Which generates…

public static final boolean equals-impl0(int[], int[]);
 Code:
   0: aload_0
   1: aload_1
   2: invokestatic  #55  // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
   5: ireturn

This is tantamount to reference equality via Object.equals, which is particularly unfortunate because while we wait on value classes to mature this is a sneaky place for reference semantics to sneak into a concept that aims to renounce object identity.

You might argue that Java primative arrays are objects, granted. However, since value classes forbid specialization of equals, there’s no way to implement anything other than reference semantics (at least with the ergonomics and expectations of using ==).

So value classes renounce identity but reserve the right to hold that identity as exalted underneath the value class’ interface.

Considering arrays to essentially be their address in memory makes little sense to me if we’re renouncing identity—at least as a default. Fortunately, there’s hope for more robust value semantics tied to Project Valhalla’s “Codes like a class, works like an int.” slogan¹. Let’s hope that pans out and doesn’t come with too many corner cases.

This is a KEEP² to watch.

1. https://cr.openjdk.java.net/~briangoetz/valhalla/sov/01-background.html

2. https://github.com/Kotlin/KEEP/blob/master/notes/value-classes.md