In the javac source code, there is a method that returns a type closure given a com.sun.tools.javac.code.Type. It is documented to work only for "class or interface type[s]". However it works for many other types as well, by returning a one-element list consisting of the type itself and nothing else, seemingly violating its own documentation:
/**
* Returns the closure of a class or interface type.
*/
public List<Type> closure(Type t) {
List<Type> cl = closureCache.get(t);
if (cl == null) {
Type st = supertype(t);
if (!t.isCompound()) { // <line 5>
if (st.hasTag(CLASS)) {
cl = insert(closure(st), t);
} else if (st.hasTag(TYPEVAR)) {
cl = closure(st).prepend(t);
} else {
cl = List.of(t);
}
} else {
cl = closure(supertype(t));
}
for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail)
cl = union(cl, closure(l.head));
closureCache.put(t, cl);
}
return cl;
}
(For any not versed in the wonderful world of the javac source code, a List is not a java.util.List, but a linked list structure, and a Type is not a java.lang.reflect.Type. A "compound" Type is basically an IntersectionType (in the language model terminology).)
So at line 5 in the excerpt above, if it is not compound (so let's pretend it's an array or a primitive type or something crazy like an executable type), and it is neither a class nor a type variable, then it is blindly added to the List that will be returned. You'll therefore get back a single element List consisting of the Type itself, if the type is not a class, interface or intersection type, and nothing else.
A concrete example:
Consider the type denoted by java.lang.Integer[]. Clearly it has a supertype (the type denoted by java.lang.Number[]), unlike, say, certain primitive types.
We know that the method itself is defined to work only on class and interface types, but it doesn't check this. Also, immediately above the method in a related section of code, we find:
A closure is a list of all the supertypes and interfaces of a class or interface type, ordered by ClassSymbol.precedes….
According to that documentation, we'd expect an empty list to be returned if we pass an array type in. But instead we get a single-element list whose sole element is the type denoted by java.lang.Integer[] (the very type we pass in).
Why is this?
(I am well aware I am looking at decades-old code and the answer might very well be: no one knows.)