The latest iteration of the user model for value classes makes it crystal clear that one value class `C` defines two types.

The second type is named `C.val` (at present, until that bikeshed is repainted). This is the “value companion” to `C`, or maybe its “companion value type”.

The term “companion” tries to capture the idea that the class doesn’t come alone but travels with some friends, its types. But this pulls in a long and difficult discussion about the exact relation between a class and a type. And then (inevitably) “what’s a class *really*?” and “what’s a type *really*?”

I think we want to make a distinction between a class and a type. A class is primarily a bunch of source code, later compiled into a classfile. A type is the primary static attribute of a variable in source code, determining its range of values and set of valid operations. As later compiled, the type determines a JVM-level type (usually what we call a field descriptor). The type probably also determines something of the eventual format of the variable in a real machine, although that’s a secret the JVM keeps.

In some of our discussions we have called the other companion type of `C`, which is the (nullable) reference type, by the name `C.ref`, as if it were something you could write in source code. Perhaps I should be saying `C.__REF` to avoid giving that impression. But perhaps not.

(A generic class can engender many, many types. Is this a whole mob of companion types? Perhaps not, but it does call for a clear term for this other relation of classes to types.)

(Note also that the “raw type” of a generic class is named by just the class name, sans type arguments: Plain `List` instead of `List<String>`. And not `List.raw`, at least not today.)

To me it seems useful to treat the two types with a certain amount of symmetry. There is one class, and two companion types, not a class (which is also a type), plus its companion (value) type.

If we do this, it makes some further sense to give them symmetrical names, `C.ref` and `C.val`. We then say that the class name `C`, used in a context that requires a type, is “just sugar” for the more exact `C.ref` (and certainly not `C.val`, or you would have used that name).

Are there other uses for `C.ref`?  I can think of just two:

- For type variables (*which are not classes*) `T.ref` (or some other bikeshed color) means “recover the reference companion, even if the generic argument was a value type”.

- For extreme stylized clarity in source code, where someone wants to emphasize that a variable is nullable. (Could this interact with null-inference schemes? Oh, certainly!)

The use `T.ref` lends weight to making the companions symmetric. You can go from `C` meaning `C.ref` to `C.val` in `List<C.val>` and then inside `List` you can go back to `C.ref`. It’s a two-way street.

There is a limit to treating the two companions symmetrically. Do we really want to allow inner declarations of the form `public companion type C.ref;`, on the grounds that we do so for the companion `C.val`? No, because reference types are “hardwired” by present JVM specifications, and presumably future ones.

Maybe we will turn, in the end, to a maximally asymmetric design, with no symmetrical treatment anywhere; no `C.ref` in particular. But the cost of that is never being able to refer unambiguously to `C` as class or as ref-type, except using informal notations or narrative prose.

At the moment, though, I like these rules, personally:

 - For a value class name `C`, `C.val` names a type.
- For any class or interface name `C`, `C.ref` names a type, meaning the same thing as `C`.
 - For any type variable `T` (in new generics), `T.ref` names a type.
- Maybe: For any type variable `T` (in specialized generics?), `T.val` also names a type. - The ref and val suffixes cannot be applied elsewhere. (So no `C.ref.val`.)

Comments?

Reply via email to