----- Original Message ----- > From: "Brian Goetz" <brian.go...@oracle.com> > To: "Remi Forax" <fo...@univ-mlv.fr>, "valhalla-spec-experts" > <valhalla-spec-experts@openjdk.java.net> > Sent: Wednesday, January 12, 2022 1:27:07 PM > Subject: Re: L-type, Q-type and class mirrors
>> Let's take a detour, and try to answer to the question, how do we do >> reflection >> on method with Q-types ? >> Given that reflection is using the class java.lang.Class, it means that we >> need >> a class that represents a L-type and a class that represent a Q-type. > > Correct. In addition to all sorts of VM reasons for this, users need a > way of distinguishing between > > m(Point.ref p) > and > m(Point p) > > with reflection, MH.Lookup, etc. > >> The class that represents a Q-type does not have to be a 'real' class, the >> same >> way int.class (Integer.TYPE) is not a real class, >> it's a mirror class that represent 'I' in the method signature, same with >> void.class (Void.TYPE) represent 'V'. > > Correct. We've been calling these "secondary mirrors". Note that with > extended primitives, it is possible (though not required) that the > secondary mirror reflect almost everything that the primary does -- > methods, fields, supertypes, etc. Alternately, they could be more like > int.class, which is pretty limited. > > Unfortunately, though, we run into a user expectation problem: users > will reasonable expect that if they reflect over > > m(Point p) > > they will get Point.class back. Since the user views "Point" as the > primary type (Point.ref is a supporting player), they'll expect > Point.class to be the "important" mirror. This asymmetry with the > current state of affairs is a challenge. There are two asymmetries, and we need to pick one. Either we allow Point.ref.class and in that case, you are right that EnclosingClass.class.getMethod("m").getParameterType(0) as to return a class that represent a QPoint;. Or we consider that Point.ref is a type, so Point.ref.class does not exist the same way List<String>.class or List<?>.class do not exist, in that case, Point.class.mirror() does not to have fields, methods, etc attached, the same way int.class has no fields/methods. In the latter case, it's also important that the secondary mirror has an invalid name, a name like "Point\mirror" or whatever that shows that it's a synthetic class so like Class.forName("int") does not work, Class.forName(Point.class.mirror()) should not work too. > >> So the class that represents a Q-type is a mirror class synthesized by the >> VM at >> runtime. >> Given that it is synthesized, i believe it should be only accessible using a >> method of java.lang.Class, >> by example >> Complex.class.mirrorType() // the name "mirror" is perhaps not the best > > Stepping back, what you're saying is to expose only Point.class, and > make it harder to get at the "other" mirror, such as by relegating it to > a method like Class::otherMirror. This is a reasonable move, but it > does run smack into the above problem -- that if there's one mirror, > users will expect Point.class to reflect the Point type they are most > familiar with, which is QPoint. see above > >> I propose to introduce a new kind of primitive class, the builtin primitive >> class, that > > Whether we call it that, or summon it by magic, we are stuck with some > form of this anyway, because of the asymmetries you've observed; the > existing int/Integer pairs have subtle differences from declared > Point/Point.ref pairs. There will have to be some special pleading for > built-in/legacy/basic primitives. > > I think where you're going is some flavor of this: > > special-legacy-backwards value class Integer > with-legacy-primitive int { ... } > > where we declare the Integer/int pair, but do so through Integer, but > declare it to be backwards from the other primitives, where there are > only eight of these allowed. yes, but i think it should be a primitive class not a value class. Rémi