----- 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

Reply via email to